Go Modules
A module is a collection of related Go packages that are versioned together as a single unit.
Modules record precise dependency requirements and create reproducible builds.
Go从1.11开始引入了原生的包管理器Go Modules, 他的前身是vgo。
Example
1 | go mod init github.com/my/repo |
go.mod
go.mod类似于node里的package.json, 里面记录了当前module所需要的直接依赖以及间接依赖。
1 | module github.com/pingcap/tidb # 模块的名字 |
除了require, go.mod还支持一些其他的指令
1 | replace example.com/some/dependency => example.com/some/dependency-fork v1.2.3 # 使用某个依赖的fork来替换这个依赖 |
版本选择
所有的原生命令都会(go get go build)都会自动更新go.mod文件(注意在$GOPATH下需要设置GO111MODULE为on), 默认会添加依赖的最新版本到go.mod。
依赖使用Pseudo-versions
commit time commit hash
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c
tag-version
go.sum
go.sum中记录了构件项目时所用的各个依赖的哈希值,用来对module进行验证
1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= |
执行go mod verify可以检查你下载的依赖是否与go.sum记录的相匹配从而提高了安全性,go module下载的module可以在$GOPATH/pkg/mod里查看。
常用命令
1 | Go {get,build,test} |
Migrate from govendor to go modules
go mod init
会自动从vendor/vendor.json中拷贝依赖, 也会自动生成一个包名,你也可以自己取一个名字,这将作为pkg的引用名字。- build your project
- 成功 done
- 失败
- 对于major version>=2的modules 需要手动在import path里加上major version如
quoteV3 "rsc.io/quote/v3"
, 但是使用起来包名还是一样的。 - 错误信息是:”unknown revision”, 这个错误的意思是远程分支没有这个commit,这时候需要确认自己需要的依赖的正确版本, 用
go get
更新对应的依赖, 然后回到步骤2。
- 对于major version>=2的modules 需要手动在import path里加上major version如
go mod tidy
, 这个命令会整理去掉不需要的依赖。- (optional) 如果因为某些原因还是需要vendor目录,可以执行
go mod vendor
会生成vendor目录(虽然官方不推荐), 目录底下有一个modules.txt文件记录了vendor的内容,编译时要使用vendor还需要加上编译参数-mod=vendor
。
注意
- go modules在$GOPATH下不是默认启用的(是的,在非$GOPATH下是默认启用的,go project可以放在任意的目录下了,看起来官方准备摒弃$GOPATH),要在$GOPATH下启用需要
export GO111MODULE="on"
。 - vendor模式下vendor目录当前不会拷贝非go语言的依赖 https://github.com/golang/go/issues/26366。