一、启用go mod
go env -w GO111MODULE=on #开启 MODULE
go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct #默认值为https://proxy.golang.org,direct
GO111MODULE可以设置为:off、on、auto(默认值),从GO111MODULE变量名可以看出,是Go1.11版本之后才出来有依赖包管理办法。
- 为
off
时,则不使用go mod,查找依赖包的顺序是:当前项目根目录/vendor
,其次是$GOPATH/src
(这是Golang1.11版本之前的用法)。 - 为
on
时,则开启go mod,查找依赖包是以当前项目根目录的go.mod
文件为基准,会忽略$GOPATH
和vendor
文件夹,只根据go.mod
下载依赖。 - 为
auto
或未设置,则go命令根据当前目录启用或禁用模块支持。仅当当前目录位于$GOPATH/src
之外且其本身包含go.mod
文件或位于包含go.mod
文件的目录下时,才启用模块支持。
GOPROXY为依赖包代理地址,由于像golang.org/x
这种依赖包需要翻墙才能下载,所以建议设置成国内镜像地址:
https://goproxy.cn 为国内七牛云维护的GO的镜像地址。
https://goproxy.io 为国内另一个镜像地址。
二、初始化go.mod
进入项目根目录(假如目录名为project1),初始化一个moudle,模块名为你的项目名,必须为英文名称,允许字母数字下划线和/
,但是不能以/
开头。
go mod init [模块名]
如果我们的项目根目录在$GOPATH/src/
中,模块名可以不填写,将自动生成,一般是与项目根目录名称同名,如project1
或github.com/project1
;如果项目根目录不在$GOPATH/src/
中,则模块名必须填写,模块名同样可以命名如project1
或github.com/project1
,也就是说模块名不一定与路径对应起来,但如果我们使用了路径,如github.com/project1
,后续也可以把项目搬到$GOPATH/src/github.com
目录下去。
执行完后,会在当前项目根目录下创建一个go.mod
文件,内容如:
module project1
go 1.13
此时还没有任何依赖包信息。
三、整理依赖包
go mod tidy
命令执行后,go mod会去项目文件中发现依赖包,将依赖包名单添加到go.mod
文件中,自动删除那些有错误或者没有使用的依赖包。
四、将依赖包拷贝到项目vendor
go mod vendor
在项目完工时,我们也可以把依赖包复制到项目根目录/vendor/
,以便存档,其实也可以不做这个操作,有go.mod
文档就够了。
项目根目录下有了vendor后,就可以这样编译:
go build -mod vendor -o ./project1 //project1为编译后的包名,或如下面,加上文件名
go build -mod vendor -o ./project1 main.go
五、其他常用命令
下载依赖包到本地缓存
go mod download
若之前拉过一次代码,会把该次go.mod
里面的版本信息缓存到$GOPATH/pkg/mod/cache
里面,
下载时如果cache有该版本信息,就用cache里面的版本信息去下载,否则重新下载。
注意:如果你已经拉取了一个tag版本下的包,若这个tag包含的信息被修改了,需要清除cache才能重新拉取这个这个更新后tag的信息。
清理本地依赖包
go clean -modcache
以上命令是go mod download
的反操作,执行后会删除放置在$GOPATH/pkg/mod/cache
下的依赖包缓存,有时依赖包出现错误,可以先清理后再重新下载到本地缓存。
添加单个依赖包
go mod edit -require=golang.org/x/text
移除单个依赖包
如果我们不再使用某个包了,可以单独移除,如:
go mod edit -droprequire=golang.org/x/text
验证依赖是否正确
go mod verify
解释为什么需要依赖
go mod why
校验所有依赖包的正确性
go mod verify
六、go.mod文档说明
go.mod
文件可以通过require,replace,exclude
语句来说明依赖包的管理规则:
require
语句用于指定必不可少的依赖包
replace
语句用于指定需要替换依赖包的地址,比如golang.org/x/text
包替换成github.com/golang/text
exclude
语句用于指定可以忽略依赖项模块
例如:
replace (
cloud.google.com/go => github.com/googleapis/google-cloud-go v0.34.0
github.com/go-tomb/tomb => gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7
go.opencensus.io => github.com/census-instrumentation/opencensus-go v0.19.0
go.uber.org/atomic => github.com/uber-go/atomic v1.3.2
go.uber.org/multierr => github.com/uber-go/multierr v1.1.0
go.uber.org/zap => github.com/uber-go/zap v1.9.1
golang.org/x/crypto => github.com/golang/crypto v0.0.0-20181001203147-e3636079e1a4
golang.org/x/lint => github.com/golang/lint v0.0.0-20181026193005-c67002cb31c3
golang.org/x/net => github.com/golang/net v0.0.0-20180826012351-8a410e7b638d
golang.org/x/oauth2 => github.com/golang/oauth2 v0.0.0-20180821212333-d2e6202438be
golang.org/x/sync => github.com/golang/sync v0.0.0-20181108010431-42b317875d0f
golang.org/x/sys => github.com/golang/sys v0.0.0-20181116152217-5ac8a444bdc5
golang.org/x/text => github.com/golang/text v0.3.0
golang.org/x/time => github.com/golang/time v0.0.0-20180412165947-fbb02b2291d2
golang.org/x/tools => github.com/golang/tools v0.0.0-20181219222714-6e267b5cc78e
google.golang.org/api => github.com/googleapis/google-api-go-client v0.0.0-20181220000619-583d854617af
google.golang.org/appengine => github.com/golang/appengine v1.3.0
google.golang.org/genproto => github.com/google/go-genproto v0.0.0-20181219182458-5a97ab628bfb
google.golang.org/grpc => github.com/grpc/grpc-go v1.17.0
gopkg.in/alecthomas/kingpin.v2 => github.com/alecthomas/kingpin v2.2.6+incompatible
gopkg.in/mgo.v2 => github.com/go-mgo/mgo v0.0.0-20180705113604-9856a29383ce
gopkg.in/vmihailenco/msgpack.v2 => github.com/vmihailenco/msgpack v2.9.1+incompatible
gopkg.in/yaml.v2 => github.com/go-yaml/yaml v0.0.0-20181115110504-51d6538a90f8
labix.org/v2/mgo => github.com/go-mgo/mgo v0.0.0-20160801194620-b6121c6199b7
launchpad.net/gocheck => github.com/go-check/check v0.0.0-20180628173108-788fd7840127
)
主要包括:golang.org google.golang.org gopkg.in go.uber.org cloud.google.com
在下载包时会有timeout 导致编译失败,以上是对应的github库的替换。
七、go get的使用
使用go mod
之后,go get
拉取依赖的方式就发生了变化:
1、老的go get取包过程类似:git clone + go install
, 开启Go Module功能后go get
就只有git clone
或者 download过程了。
2、新老实现还有一个不同是,两者存包的位置不同。前者,存放在$GOPATH/src
目录下;后者,存放在$GOPATH/pkg/mod
目录下。
3、老的go get
取完主包后,会对其repo下的submodule
进行循环拉取。新的go get
不再支持submodule
子模块拉取。
查看指定包可以下载的版本
go list -m -versions github.com/gogf/gf
下载项目依赖
go get ./...
拉取最新的版本(优先择取 tag)
go get golang.org/x/text@latest
拉取 master 分支的最新 commit
go get golang.org/x/text@master
拉取 tag 为 v0.3.2 的 commit
go get golang.org/x/text@v0.3.2
拉取 hash 为 342b231 的 commit,最终会被转换为 v0.3.2:
go get golang.org/x/text@342b2e
指定版本拉取,拉取v3版本
go get github.com/smartwalle/alipay/v3
更新
go get -u
八、go mod与原GOPATH的区别
1、环境变量GOPATH
不再用于解析imports包路径,即原有的$GOPATH/src/
下的包,通过import是找不到了
2、Go Module功能开启后,下载的包将存放与$GOPATH/pkg/mod
路径
3、$GOPATH/bin
路径的功能依旧保持
总结
在Go1.11版本之前,依赖包管理一直是GOPATH的包管理方式,不太灵活方便,1.11版本发布后,带来了全新的go mod
管理方式,用官方的话说,这是 GOPATH 的替代方案,集成了对版本控制和软件包分发的支持。可以看出借鉴了nodejs等包管理方式,项目的创建不再需要放在固定的$GOPATH/src/
路径中,配合着国内的依赖包镜像源,体验很顺滑,推荐!
有疑问加站长微信联系(非本文作者)