文章目录
- Go Modules介绍
- 创建一个module
- 添加外部依赖
- 升级版本
- 移除没有使用的依赖
- 下载依赖到当前目录
- 老项目的迁移
Go Modules介绍
为了解决Go包管理的问题,Go从1.11开始加入了Go Modules这一新特性。让包的依赖和版本管理更加容易。
一个
module
可以理解为一个单独的包或者模块,
module
的根目录下会包含一个
go.mod
文件。
go.mod
文件中定义了该
module
被其它包
import
的
path
,同时也包含了该
module
中依赖哪些包,和这些包的版本号。
Go 1.11需要设置GO111MODULE来开启module功能GO111MODULE=on,会开启使用moduleGO111MODULE=auto默认值,会根据当前目前来决定是否开启module。如果当前目录在``GOPATH/src``之外且当前目录有``go.mod``文件或当前文件在包含go.mod文件的目录下面从Go 1.13开始module被默认开启
创建一个module
在非
GOPATH/src
目录下创建一个空文件夹
hello
,然后在文件夹下创建
hello.go
文件:
package hellofunc Hello() string {return \"Hello, world.\"}
写一个单测文件
hello_test.go
:
package helloimport \"testing\"func TestHello(t *testing.T) {want := \"Hello, world.\"if got := Hello(); got != want {t.Errorf(\"Hello() = %q, want %q\", got, want)}}
运行go test命令,这个时候返回:
PS D:\\Code\\hello> go testPASSok _/D_/Code/hello 0.176s
可以看到当前的目录是在
D:\\Code\\hello
,不在
GOPATH/src
目录下,这时我们并没有创建module,但是go在运行时创造了一个假的module名称是:
_/D_/Code/hello
接下来运行
go mod init
命令,创建一个module并且运行单测:
go mod init example.com/hellogo: creating new go.mod: module example.com/hellogo testPASSok example.com/hello 0.177s
可以看到case运行通过,并且返回
ok example.com/hello 0.177s
就是是我们刚才创建的module。在目录下面也可以看多了一个
go.mod
文件它的内容是:
module example.com/hellogo 1.14
mod
是在
module
的根目录下创建的,子目录的
import path
是module的
path
加上子目录的地址。
添加外部依赖
在hello.go文件中导入一个外部的包:
package helloimport \"rsc.io/quote\"func Hello() string {return quote.Hello()}
运行单测:
go: finding module for package rsc.io/quotego: found rsc.io/quote in rsc.io/quote v1.5.2--- FAIL: TestHello (0.00s)hello_test.go:8: Hello() = \"你好,世界。\", want \"Hello, world.\"PASSok example.com/hello 0.177s
这时打开
go.mod
文件:
module example.com/hellogo 1.14require rsc.io/quote v1.5.2
可以发现go会自动去找
rsc.io/quote
这个依赖的最新版本同时加入到
go.mod
文件中,再次运行单测:
PASSok example.com/hello 0.177s
可以发现
go
第二次已经不需要去找
rsc.io/quote
。运行
go list -m all
返回:
example.com/hellogolang.org/x/text v0.0.0-20170915032832-14c0d48ead0crsc.io/quote v1.5.2rsc.io/sampler v1.3.0
可以看到引入外部依赖
rsc.io/quote
,也会带来它的间接依赖
除了
go.mod
文件,目录中也会增加一个
go.sum
文件内容如下:
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
后面增加了每个外部依赖内容的hash值,go通过这些hash值去验证你下载依赖的正确性。
升级版本
通过上面的
go list -m all
可以看到
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
我们用到的版本是
v0.0.0-20170915032832-14c0d48ead0c
。我们接下来升级它的版本:
go get golang.org/x/textgo: golang.org/x/text upgrade => v0.3.3go: downloading golang.org/x/text v0.3.3go testPASSok example.com/hello 0.199s
此时
go.mod
文件内容是:
module example.com/hellogo 1.14require (golang.org/x/text v0.3.3 // indirectrsc.io/quote v1.5.2)
可以看到
golang.org/x/text v0.3.3 // indirect
这个间接依赖已经被升级到
v0.3.3
了。
运行
go list -m all
返回:
example.com/hellogolang.org/x/text v0.3.3golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6ersc.io/quote v1.5.2rsc.io/sampler v1.3.0
移除没有使用的依赖
运行
go mod tidy
可以删除没有使用的包
下载依赖到当前目录
go mod vendor
会下载依赖到vendor中,只会下载你代码中的依赖,不会下载所有go.mod中引用的依赖
老项目的迁移
打开老项目的目录一般是在
GOPATH/src
下面,然后运行
go mod init xxxgo build
需要注意的是迁移项目可能会出现包冲突的问题,会报类似
cannot load xxxx: ambiguous import: found xxxx in multiple modules:
这样的错误,这时可能需要再go.mod中手动指定这个包的版本号