Go的1.11和1.12版本包括对模块--新的Go依赖管理系统的初步支持,使依赖版本信息变得明确且更易于管理。这篇博客文章介绍了开始使用模块所需的基本操作。
模块是存储在根目录有一个 go.mod
文件的文件树中的 Go 包(package)的集合。go.mod
文件定义了模块的module path(也是模块根目录的导入路径)以及模块依赖的其他模块的要求,满足了依赖要求模块才能被成功构建起来。每个依赖模块的要求被写为一个模块路径和相应的模块版本。
下面展示了一个简单的go.mod
文件
module example.com/hello
go 1.12
require rsc.io/quote v1.5.2
从Go 1.11开始,当当前目录或任何父目录有go.mod
时,只要该目录位于$GOPATH/src
之外,go命令就可以使用模块。 (在$ GOPATH/src
内部,出于兼容性考虑,即使找到了go.mod
,go命令仍然在旧的GOPATH模式下运行。)从Go 1.13开始,模块模式将是所有开发的默认模式。
本文介绍了使用模块开发Go代码时出现的一系列常见操作:
- 创建一个新模块。
- 添加模块的依赖项。
- 升级模块的依赖项。
- 增加依赖项的主版本。
- 将依赖项升级到新的主版本。
- 删除未使用的依赖项。
创建一个新模块
在$GOPATH/src
之外的某个地方创建一个新的空目录,然后在新目录下创建一个新的源文件hello.go
:
package hello
func Hello() string {
return "Hello, world."
}
同时编写它的测试文件hello_test.go
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)
}
}
假设我们新建的目录为/home/gopher/hello
,此时该目录包含一个包,而不是模块,因为目录中没有go.mod
文件。使用 go 命令运行测试会看到:
$ go test
PASS
ok _/home/gopher/hello 0.020s
$
输出的最后一行汇总了整个包的测试信息。因为我们工作在$GOPATH
和任意模块之外,go 命令不知道当前目录的导入路径(导入路径是标识包的唯一字符串标识)所以根据目录所在位置创建了一个假的导入路径_/home/gopher/hello
让我们使用go mod init
将当前目录设为一个模块的根目录,然后再次执行go test
:
$ go mod init example.com/hello
go: creating new go.mod: module example.com/hello
go mod init
命令编写了一个go.mod
文件:
$ cat go.mod
module example.com/hello
go 1.12
$
go.mod
仅出现在模块的根目录中。位于子目录中的包的导入路径将由模块路径加上子目录路径组成。比如说如