-
Notifications
You must be signed in to change notification settings - Fork 0
Description
-
Go 1.13及以后版本GO111MODULE=auto的行为变化。
GO111MODULE的默认值依然为auto。但无论repo是否在GOPATH,只要目录有go.mod,go编译器都会使用go module来管理依赖
-
如何创建模块
新建工作区和项目文件夹
$ mkdir -p $HOME/Desktop/go/hello $ cd $HOME/Desktop/go/hello $init mod init $path
一是作为模块标识,二是作为模块的import path
此时会生成go.mod文件
当其他项目引用这个模块下的 package 时都会以该 import $path 作为共同的前缀$ go mod init example.com/hello go: creating new go.mod: module example.com/hello $ cat go.mod module example.com/hello go 1.15 $新建go文件
hello.gopackage hello func Hello() string { return "Hello, world." }新建测试文件
hello_test.go,测试是否能正常调用Hello方法package hello import "testing" func TestHello(t *testing.T) { want := "Hello, world." if got := Hello(); got != want { t.Errorf("Hello() = %q, want %q", got, want) } }运行测试文件
$ go test PASS ok example.com/hello 1.221s $ -
如何添加依赖项
修改hello.go。用rsc.io/quote来实现Hello
package hello import "rsc.io/quote" func Hello() string { return quote.Hello() }再次运行测试。看来Hello()方法实现了国际化功能,需要修改一下测试用例。
... func TestHello(t *testing.T) { want := "你好,世界。" if got := Hello(); got != want { t.Errorf("Hello() = %q, want %q", got, want) } }测试通过了,证明Hello功能正常
$ go test PASS ok example.com/hello 0.377s $此时会把直接依赖写到go.mod中
$ cat go.mod module example.com/hello go 1.15 require rsc.io/quote v1.5.2 $尝试列出目前的所有依赖。当前模块(主模块)始终是第一行,随后的才是真正的依赖关系
$ go list -m all example.com/hello golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c rsc.io/quote v1.5.2 rsc.io/sampler v1.3.0尝试列出所有的依赖关系。清晰明了,这个功能大赞
$ go mod graph example.com/hello rsc.io/quote@v1.5.2 rsc.io/quote@v1.5.2 rsc.io/sampler@v1.3.0 rsc.io/sampler@v1.3.0 golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c所有真正的依赖和哈希值会记录到go.sum中。哈希值的作用是确保所有依赖项不会被恶意修改。
$ cat 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= -
如何更新依赖项。版本号最好带着语义信息,v0.1.2。主要版本是0,次要版本是1,补丁版本是2
尝试升级一下golang.org/x/text
$ go get golang.org/x/text go: golang.org/x/text upgrade => v0.3.3 go: downloading golang.org/x/text v0.3.3 $执行go list -m all并且看看go.mod和go.sum情况。
golang.org/x/text已经升级到v0.3.3版本,go.mod也改成了golang.org/x/text v0.3.3 // indirect。
indirect表示该依赖不是由当前项目直接依赖,而是由其他依赖包间接依赖的。$ go list -m all example.com/hello golang.org/x/text v0.3.3 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e rsc.io/quote v1.5.2 rsc.io/sampler v1.3.0 $ cat go.mod module example.com/hello go 1.15 require ( golang.org/x/text v0.3.3 // indirect rsc.io/quote v1.5.2 ) $ cat 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= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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=尝试升级rsc.io/sampler。发现版本太先进,兼容不了旧版本
$ go get rsc.io/sampler go: rsc.io/sampler upgrade => v1.99.99 go: downloading rsc.io/sampler v1.99.99 $ go test --- FAIL: TestHello (0.00s) hello_test.go:8: Hello() = "99 bottles of beer on the wall, 99 bottles of beer, ...", want "Hello, world." FAIL exit status 1 FAIL example.com/hello 0.014s $尝试列出可用的版本以及挑选一个补丁版本。go get默认是获取@latest版本
$ go list -m -versions rsc.io/sampler rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99 $ go get rsc.io/sampler@v1.3.1此时。$GOPATH/pkg/mod/rsc.io存在rsc.io/sampler的多个版本
$ cd $HOME/go/pkg/mod/rsc.io $ ls quote@v1.5.2 sampler@v1.3.0 sampler@v1.3.1 sampler@v1.99.99 $ -
如何引用同一个依赖的不同主版本
修改hello.go。引用rsc.io/quote/v3
package hello import ( "rsc.io/quote" quoteV3 "rsc.io/quote/v3" ) func Hello() string { return quote.Hello() } func Proverb() string { return quoteV3.Concurrency() }给测试文件添加以下行
... func TestProverb(t *testing.T) { want := "Concurrency is not parallelism." if got := Proverb(); got != want { t.Errorf("Proverb() = %q, want %q", got, want) } }再次测试一下
$ go test PASS ok example.com/hello 0.377s $此时项目同时依赖rsc.io/quote和rsc.io/quote/v3
$ go list -m rsc.io/q... rsc.io/quote v1.5.2 rsc.io/quote/v3 v3.1.0总结:
- 主要版本不相同时要发布不同的模块,模块必须以版本号结尾
- 相同主要版本之间要兼容
- 像rsc.io/quote如果有多个主要版本。需要发布rsc.io/quote,rsc.io/quote/v2和rsc.io/quote/v3等模块
-
引用同一个依赖的不同版本毕竟不是什么好事。尝试将旧的api升级到新的api,然后将旧的依赖删除。
查看rsc.io/quote/v3版本有什么api。像是Hello升级到了HelloV3
$ go doc rsc.io/quote/v3 package quote // import "rsc.io/quote/v3" Package quote collects pithy sayings. func Concurrency() string func GlassV3() string func GoV3() string func HelloV3() string func OptV3() string $修改hello.go,更换一下api
package hello import quoteV3 "rsc.io/quote/v3" func Hello() string { return quoteV3.HelloV3() } func Proverb() string { return quoteV3.Concurrency() }既然没有了多个版本,可以不用alias
package hello import "rsc.io/quote/v3" func Hello() string { return quote.HelloV3() } func Proverb() string { return quote.Concurrency() }重新运行test。一切正常
$ go test PASS ok example.com/hello 1.626s -
如何删除已下载但未引用的依赖。例如
rsc.io/quote$ go list -m all example.com/hello golang.org/x/text v0.3.3 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e rsc.io/quote v1.5.2 rsc.io/quote/v3 v3.1.0 rsc.io/sampler v1.3.1 $ cat go.mod module example.com/hello go 1.15 require ( golang.org/x/text v0.3.3 // indirect rsc.io/quote v1.5.2 rsc.io/quote/v3 v3.1.0 rsc.io/sampler v1.3.1 // indirect )利用tidy命令删除未使用的依赖项
$ go mod tidy $ go list -m all example.com/hello golang.org/x/text v0.3.3 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e rsc.io/quote/v3 v3.1.0 rsc.io/sampler v1.3.1 $ cat go.mod module example.com/hello go 1.15 require ( golang.org/x/text v0.3.3 // indirect rsc.io/quote/v3 v3.1.0 rsc.io/sampler v1.3.1 // indirect )重新测试
$ go test PASS ok example.com/hello 3.088s