golang module 使用教程
Go module 是golang最新的包管理工具,可以使依赖包版本信息更明确与可控。module 是关于Go packages的集合,存储在根目录下的go.mod文件中,go.mod 定义了模块的模块路径以及模块的依赖属性,依赖属性包含模块路径以及特定寓意的版本信息。
需要注意的是:在Go 1.13之前go module 在GOPATH下是默认不开启的,这是为了兼容的需要,如果需要使用go module可以在GOPATH/src外的路径创建go.mod文件。
本文会介绍Go module的一些基本用法;
- 常见命令
 - 创建一个模块
 - 添加一个依赖
 - 升级依赖
 - 其他命令
 
常见命令
go mod 提供了以下命令
- download: 下载依赖包到本地缓存 ($GOPATH/pkg/mod), 该目录下的包所有项目共享;
 - edit : 编辑go.mod;
 - graph: 打印模块的依赖图;
 - init: 在当前目录初始化mod;
 - tidy : 添加缺失的依赖包并清理没有使用的包;
 - vendor : 将依赖包复制到vendor目录;
 - verify: 验证依赖是否正确;
 - why : 解释为什么需要这个依赖;
 
创建一个模块
如前文所说在GOPATH外的创建一个目录,例如 ~/gomod/hello;
执行一下子命令
1 ~/gomod/hello$ go mod init example.com/hello
2go: creating new go.mod: module example.com/hello
创建hello.go
1package hello
2
3func Hello()string {
4	return "Hello, world."
5}
为使用SayHi,创建test文件 hello_test.go
 1package hello
 2
 3import "testing"
 4
 5func TestHello(t *testing.T) {
 6	want := "Hello, world."
 7	if got := Hello(); got != want {
 8		t.Errorf("Hello() = %s, want %s", got, want)
 9	}
10}
执行测试用例
1 ~/gomod/hello$ go test -run TestHello
2PASS
3ok  	example.com/hello	0.006s
添加一个依赖
1package hello
2
3import "rsc.io/quote"
4func Hello()string {
5	return quote.Hello()
6}
执行
1go: extracting rsc.io/quote v1.5.2
2go: extracting rsc.io/sampler v1.3.0
3PASS
4ok  	example.com/hello	0.009s
此时会将代码下载到$GOPATH/pkg/mod目录下,之后运行不会重复下载,可以到go.mod已经更新了
1module example.com/hello
2
3go 1.12
4
5require rsc.io/quote v1.5.2
使用 go list -m all 可以查看所有依赖
1$ go list -m all
2example.com/hello
3golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
4rsc.io/quote v1.5.2
5rsc.io/sampler v1.3.0
此时目录下多了一个go.sum文件,这个文件是做什么的呢?
1golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
2golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
3rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
4rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
5rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
6rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
可以看出该文件存储了包的路径 版本 还有校验值;每次执行命令时都会check 该校验是否与download目录下的是否一致;不一致就会报错
1verifying rsc.io/quote@v1.5.2/go.mod: checksum mismatch
2	downloaded: h1:Q15uSTpOVzCmer7yFUWKviBR7qLGLuYQ5zPmjACcaxQ=
3	go.sum:     h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
升级依赖
加入要把quote包升级到其他版本,比如v3(需要提前知道升级的版本以及其中函数),
1package hello
2
3import (
4	quoteV3 "rsc.io/quote/v3"
5)
6func Hello()string {
7	return quoteV3.HelloV3()
8}
运行 go test, 会自动下载V3
1go test
2go: downloading rsc.io/quote/v3 v3.1.0
3go: extracting rsc.io/quote/v3 v3.1.0
4PASS
5ok  	example.com/hello	0.008s
查看 go.mod
1module example.com/hello
2
3go 1.12
4
5require (
6	golang.org/x/text v0.3.2 // indirect
7	rsc.io/quote v1.5.2
8	rsc.io/quote/v3 v3.1.0
9)
并没有删除 rsc.io/quote v1.5.2 ,这需要执行 go mod tidy 来去除不使用的包。
 1$ go mod tidy
 2$ cat go.mod
 3module example.com/hello
 4
 5go 1.12
 6
 7require (
 8	golang.org/x/text v0.3.2 // indirect
 9	rsc.io/quote/v3 v3.1.0
10)
其他命令
- replace 替换依赖项模块: 可以将包替换成另一个包或者不同版本;
 - exclude 忽略依赖项模块;
 
总结
- go mod init 创建一个模块,并创建文件go.mod;
 - go build , go test 还有其他关于编译的命令都会按需将依赖添加到go.mod;
 - go list -m all 输出当前模块所有的依赖;
 - go mod tidy 可以删除不使用的依赖;