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 可以删除不使用的依赖;

参考

using-go-modules

Posts in this Series