Loading

Golang依赖管理

Golang依赖管理

其实我是很喜欢golang这门语言的,易开发,易维护,社区庞大且相对成熟,不过可惜它是谷歌的.

其实谷歌也没什么,主要是谷歌的东西容易用着用着就不能用了.

最早之前用golang的时候,就发现go get这个命令安装东西时如果有golang官方的依赖就会发现被墙了,用起来非常的麻烦.不过当时服务器部署在海外,一切都还好.

今天就记录一下在国内使用包时免FQ的办法 gopm(gopem项目已经下了,推荐使用go mod)

go get

在项目中执行go get命令可以下载依赖包默认自动执行install,还可以指定下载的版本.

用法
用法:go get [-d] [-f] [-t] [-u] [-fix] [-insecure] [build flags] [packages]

go get package@version将会升级到指定的版本号version
go get -u=patch将会升级到最新的修订版本
go get -u将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)

参数

-v 打印出被构建的代码包的名字
-x 打印出用到的命令
-d 只下载不安装
-u 让命令利用网络来更新已有代码包及其依赖包,默认情况下,该命令只会下载本地不存在的包,并不会更新已有的代码包.
-f 仅在使用-u标记时才有效,该标记会让命令程序忽略掉对已下载代码包的导入路径的检查。如果下载并安装的代码包所属的项目是你从别人那里Fork过来的,那么这样做就尤为重要了。
-fix 让命令程序在下载代码包后先执行修正动作,而后再进行编译和安装。
-insecure 允许命令程序使用非安全的scheme(如HTTP)去下载指定的代码包。如果你用的代码仓库(如公司内部的Gitlab)没有HTTPS支持,可以添加此标记。请在确定安全的情况下使用它。
-t 让命令程序同时下载并安装指定的代码包中的测试源码文件中依赖的代码包。

Go 1.16 起,不推荐通过go get来安装包也就是说,go get只用来下载包,且将来版本可能会给该命令始终加上-d.

Go 1.16 建议这么用
go get -d github.com/XXX
这只会下载并不会构建和安装,且将来 go get 只会用来下载.

go mod

使用go modgo proxy来做依赖管理go 1.13>=版本推荐使用

依赖管理三个阶段GOPATH,GOVENDOR,go mod

  • GOPATH 需要多个版本的时候,GOPATH无法做到,而且所有项目都必须放到这里的话多了之后会很要命.
  • GOVENDOR 什么都要放进去,非常费劲和臃肿.所以社区出了glide等第三方工具帮我们
  • go mod 推荐使用,非常完美,go命令统一管理,用户不必关心目录结构,项目也不再必须放在~/go/src/下了
  • go mod下载的包都在~/go/pkg/mod/下存储

go mod模式默认忽略vendor目录,可以通过flag-mod=vendor设置为GOFLAGS=-mod=vendor来设置为vendor模式.但是该模式下无法正常使用go get

只通过goproxy来下载依赖不用go mod

go 1.13以下版本推荐使用

    1. 仅设置当前窗口本次生效.
      开启GOPOXY地址即可,go 1.13一下版本没有GO111MODULE这个变量
export GOPROXY=https://goproxy.cn
    1. 此时就可以直接使用go get命令而不会被墙了,下载的内容还是存储在GOPATH中

这个包有一个golang.org的依赖如果直接go get是无法下载的.

go get -u -v github.com/aliyun/aliyun-oss-go-sdk/oss

完成

完全使用go mod

go mod 常用命令

go get 下载/升级依赖,go mod不再下载源码进$GOPATH/src,而是在$GOPATH/pkg/mod

go list -m all 打印当前module的依赖包。也可以添加 -json 参数,例如: go list -m -json all
go mod init 初始化当前文件夹, 创建go.mod文件
go mod download 下载依赖到$GOPATH/pkg/mod目录
	-x 打印执行的命令
	-json 以json的格式展示依赖的包
go mod edit 编辑go.mod文件
    -fmt 格式化go.mod文件
    -require=golang.org/x/text [@版本号]添加依赖项
    -droprequire=golang.org/x/tex [@版本号] 移除依赖项
	-replace=AAA@版本号=BBB@版本号 将AAA替换为BBB(go.mod中会增加replace模块)例如AAA被墙需要从github下载时可以用这个
go mod graph       打印模块依赖图
go mod tidy        增加缺少的module,删除无用的module
    -v 展示详情
go mod vendor      将依赖复制到vendor下
go mod verify      校验依赖
go mod why         解释为什么需要依赖

执行案例

不指定版本号下载
go mod download golang.org/x/text
指定版本号下载
go mod download golang.org/x/text@v0.3.7
go mod download google.golang.org/appengine@v1.6.1
替换,将从golang下载的包替换为从github下载
go mod edit -replace=golang.org/x/text@v0.3.7=github.com/golang/text@v0.3.7

注意:
go mod模式不推荐使用vendor目录,而是直接从cache使用下载的包.

配置go mod

  • 永久修改
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

# 或者使用下面这个, https://goproxy.cn是七牛云的项目
go env -w GOPROXY=https://goproxy.io,direct

GOPROXY=https://goproxy.cn,direct 配置`GOPROXY`的地址`direct`代表当`go`在抓取目标模块时直接去目标模块的源头(比如 GitHub) 去抓取
GO111MODULE=on  开启`go mod`依赖管理功能

如果有不想走proxy的可以这样设置

# 设置不走 proxy 的私有仓库,多个用逗号相隔
go env -w GOPRIVATE=*.corp.example.com
# 例如:来自码云,gitlab,阿里云的的代码不走proxy
go env -w GOPRIVATE=*.gitee.com,code.aliyun.com

此时已可以获取包了

# 这时候使用go get 去获取之前下不到的包,会发现非常的快.
 go get -u -v go.uber.org/zap 
  • 后面我们用goland创建项目时会自动在项目下生成一个go.mod文件

go.mod文件内容

module awesome-project  项目名称

go 1.13  语言的版本
  • awesome-project项目目录下go get下载所需要的包

此时我们就可以为不同的项目下载不同的包了

# 这时候使用go get 去获取之前下不到的包,会发现非常的快.
 go get -u -v go.uber.org/zap 
 # 如果要下载指定版本的包只需要在后面@版本号即可
 go get -u -v go.uber.org/zap@v1.11
 # 如果要升级,不指定版本号即可
  go get -u -v go.uber.org/zap
 # 清洁依赖,删除`go.mod`中没有被使用的包的条目(不会删除包文件)
 go mod tidy
 
  • 下载完毕之后会发现go.mod文件已有改变,并且多了一个go.sum文件

go.mod文件内容

  • module定义包名

  • require定义依赖包及版本

  • indirect表示间接引用

  • replace表示被替换的包

module awesome-project 项目名

go 1.13	语言版本
 
require (  
  go.uber.org/atomic v1.5.1 // indirect 间接引用
  go.uber.org/multierr v1.4.0 // indirect  
  go.uber.org/zap v1.13.0 // indirect  
  golang.org/x/lint v0.0.0-20200130185559-910be7a94367 // indirect  
  golang.org/x/tools v0.0.0-20200206050830-dd0d5d485177 // indirect
  golang.org/x/text v0.3.7 // indirect
)

replace golang.org/x/text v0.3.7 => github.com/golang/text v0.3.7

go.sum文件的部分内容,里面有各个包的hash和版本号

github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
......
  • 直接在代码中import没有下载的包

首次直接编译会失败(goland没事).但同时也会将包下载下来, 再次编译的时候就没问题了
.

package main

import "github.com/astaxie/beego"

func main()  {
	beego.Run()
}
  • 再次查看go.mod

发现多了一条beego的记录,可见go会帮我们自动下载需要的依赖

module awesome-project

go 1.13

require (
	github.com/astaxie/beego v1.12.0 // indirect
	github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
)
  • 之前没有用go mod现在想用怎么办?

  • 使用go mod命令来创建go.mod然后再编译

go mod init module名称(会自动命名为项目名称, 一般和项目名保持一致即可)
go build ./...

build过程中每次遇到import都会触发go modules通过镜像帮我们拉去所需要的包

# 将当前目录下所有的go文件全部编译
go build ./...

# 编译案例,可以看到build后都已经在下载所需要的包了
go build ./...
go: finding github.com/go-sql-driver/mysql v1.5.0
go: finding github.com/go-xorm/xorm v0.7.9
go: downloading github.com/go-sql-driver/mysql v1.5.0
go: downloading github.com/go-xorm/xorm v0.7.9
go: finding gopkg.in/fatih/set.v0 v0.2.1
go: finding github.com/gorilla/websocket v1.4.1
go: finding github.com/pkg/errors v0.9.1
go: downloading github.com/gorilla/websocket v1.4.1
go: downloading github.com/pkg/errors v0.9.1
go: downloading gopkg.in/fatih/set.v0 v0.2.1
go: extracting github.com/go-sql-driver/mysql v1.5.0
go: extracting github.com/gorilla/websocket v1.4.1
go: extracting github.com/pkg/errors v0.9.1
go: extracting github.com/go-xorm/xorm v0.7.9
go: extracting gopkg.in/fatih/set.v0 v0.2.1

完成

使用vendor

这是一个很短暂的项目,官方在推出vendor支持以后很快就推出了go mod,不建议再用,费劲.

即在项目目录下新建一个vendor目录, 将所有依赖的第三方包全部放在vendor下.

go语言会优先在此目录寻找依赖.

可以看到vendor下面还有vendor,不管有我们的vendor,还有我们引用第三方时,他们自己的vendor

├── vendor
│   ├── config
│   └── github.com
│       ├── aliyun
│       │   └── aliyun-oss-go-sdk
│       │       ├── oss
│       │       └── sample
│       ├── go-sql-driver
│       │   └── mysql
│       ├── julienschmidt
│       │   └── httprouter
│       └── tencentyun
│           └── cos-go-sdk-v5
│               ├── costesting
│               ├── debug
│               ├── example
│               │   ├── batch
│               │   ├── bucket
│               │   ├── object
│               │   ├── service
│               │   └── sts
│               └── vendor
│                   └── github.com
│                       ├── google
│                       │   └── go-querystring
│                       │       └── query
│                       ├── mozillazg
│                       │   └── go-httpheader
│                       └── stretchr
│                           └── testify
│                               ├── _codegen
│                               ├── assert
│                               ├── http
│                               ├── mock
│                               ├── require
│                               ├── suite
│                               └── vendor
│                                   └── github.com
│                                       ├── davecgh
│                                       │   └── go-spew
│                                       │       └── spew
│                                       ├── pmezard
│                                       │   └── go-difflib
│                                       │       └── difflib
│                                       └── stretchr
│                                           └── objx

直接从github下载需要的包到$GOPATH下

没网的时候可以这么干,但是要注意依赖的依赖,这个问题.

gopm 包管理工具使用(2019年底的开始已经不能用了)

gopm官方文档

GitHub地址

GitHub中文文档

官网地址

gopm安装

go get -v -u github.com/gpmgo/gopm

gopm常用命令

# 查看当前工程依赖
gopm list
# 显示依赖详细信息
gopm list -v
# 列出文件依赖
gopm list -t [file]
# 拉取依赖到缓存目录
gopm get -r xxx
# 仅下载当前指定的包
gopm get -d xxx
# 拉取依赖到$GOPATH
gopm get -g xxx
# 检查更新所有包
gopm get -u xxx
# 拉取到当前所在目录
gopm get -l xxx
# 运行当前目录程序
gopm run
# 生成当前工程的 gopmfile 文件用于包管理
gopm gen -v
# 根据当前项目 gopmfile 链接依赖并执行 go install
gopm install -v
# 更新当前依赖
gopm update -v
# 清理临时文件
gopm clean
# 编译到当前目录
gopm bin

gopm使用案例


安装gopm
go get -v -u github.com/gpmgo/gopm

这是我们回到~/go 中的我们自己的GOPATH的目录 ls一下

可以看到$GOPATH下的src下多了一个github.com 的目录,和我们的目录放在一起
​```shell
    ~/go ⌚ 2:06:05
    $ tree -L 2
    .
    ├── bin
    │   └── gopm
    └── src
        ├── github.com
        └── learnGo

这时候我们到~/go/bin/gopm 运行该文件

~/go/bin/gopm get -g -v -u golang.org/x/tools/cmd/goimports

这是安装成功之后, $GOPATH 下的src中会多一个golang.org的目录和我们的目录放在一起

~/go ⌚ 2:19:31
$ tree -L 2
.
├── bin
│   └── gopm
└── src
    ├── github.com
    ├── golang.org
    └── learnGo

很显然我们在编码时的目录也是在src中运行的, bin是可执行文件

在~/go/bin 目录下执行 go install 安装goimports 安装之后会在~/go/bin目录下生成一个可执行的文件
~/go/bin ⌚ 2:26:38
$ go install  ../src/golang.org/x/tools/cmd/goimports
posted @ 2021-11-08 00:25  我爱吃炒鸡  阅读(485)  评论(0编辑  收藏  举报