基本介绍
Go Module是Go语言的官方依赖管理解决方案,其提供了一种简单、可靠的方式来管理项目的依赖关系。Go Module于Go1.11发布,并于Go1.14准备正式用于生产,Go官方也鼓励用户从其他的依赖管理工具迁移到Go Module。
Go Module主要解决了如下几个问题:
相关环境变量
通过go env命令可以查看与Go相关的环境变量信息。如下:

其中,与Go Module相关的环境变量主要有如下几个:
说明一下:
go env -w GO111MODULE=on命令开启Go Module功能。初始化项目
go mod init命令用于初始化一个新的Go模块,该命令会在当前目录下创建一个名为go.mod的文件。如下:

生成的go.mod文件如下:
module github.com/chenlong-cxy/go-module-test
go 1.20
鉴于当前go.mod文件的内容过于简单,为了进一步讲解go.mod文件的内容,下面给出一个较为复杂的go.mod文件示例。如下:
module module-path
go 1.20
require (
github.com/zhagnsan/test1 v1.1.3
github.com/zhagnsan/test2 v1.2.3
github.com/zhagnsan/test3 v1.2.4 // indirect
)
replace github.com/zhangsan/test1 v1.1.3 => github.com/lisi/test1 v1.3.4
replace github.com/zhangsan/test2 v1.2.3 => github.com/lisi/test2 v1.3.4
exclude (
github.com/zhangsan/test1 v1.1.1
github.com/lisi/test2 v1.2.3
)
go.mod文件大致包括如下几个部分:
说明一下:
管理依赖项
go mod edit命令用于编辑go.mod文件的内容。常用的选项如下:
为了演示Go Module的使用,我们在项目目录下分别创建main文件夹和model文件夹,main文件夹中包含一个main.go文件,model文件夹中包含一个student.go文件。如下:

其中,student.go文件中定义了一个Student结构体,并对外提供了一个函数用于创建Student实例。如下:
package model
type Student struct {
Name string
Age int
}
func NewStudent(name string, age int) Student {
return Student{
Name: name,
Age: age,
}
}
main.go中创建了一个Student实例,并通过logrus模块中的Infof函数对其进行了打印。如下:
package main
import (
"github.com/chenlong-cxy/go-module-test/model"
"github.com/sirupsen/logrus"
)
func main() {
stu := model.NewStudent("Alice", 14)
logrus.Infof("student info is %+v", stu)
}
由于项目当中用到了logrus模块,因此需要通过go mod edit命令在go.mod文件中添加logrus模块的依赖声明。如下:

执行命令后可以看到,go.mod文件中新增了对应的require条目。如下:
module github.com/chenlong-cxy/go-module-test
go 1.20
require github.com/sirupsen/logrus v1.9.3
说明一下:
import "模块路径/包相对于模块的路径"的方式导入对应的包,导入当前项目中的包也是如此。获取依赖项
go mod download命令用于下载项目所依赖的各个模块,其会根据go.mod文件下载相应的模块到Go Module缓存中。如下:

执行go mod download命令后,会在当前目录下生成一个名为go.sum的文件,该文件用于记录当前模块所依赖的各个模块的校验和信息。当前go.sum文件内容如下:
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
与此同时,在Go Module缓存路径下可以看到被下载的模块。如下:

说明一下:
$HOME/go/pkg/mod将会作为Go Module的缓存路径,用于存放Go Module下载的模块,但如果你设置了GOPATH环境变量,那么$GOPATH/pkg/mod将优先作为Go Module的缓存路径。整理依赖项
go mod tidy命令用于自动管理项目的依赖项,该命令会检测当前项目缺失的依赖项、不再使用的依赖项以及依赖项的版本是否需要更新,并自动对所需的依赖项进行下载,然后更新go.mod和go.sum文件。如下:

例如,在当前项目执行go mod tidy命令后,其检测到项目中有一个间接依赖的模块未被添加,于是会自动下载缺失的依赖项,并将其添加到go.mod文件中。如下:
module github.com/chenlong-cxy/go-module-test
go 1.20
require github.com/sirupsen/logrus v1.9.3
require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
至此当前的项目已经可以运行了,运行程序后可以看到通过logrus模块输出的Student信息。如下:

导入vendor目录
go mod vendor命令用于将项目依赖的各个模块,复制到项目的vendor目录中。如下:

执行go mod vendor命令后,在项目目录下会生成一个vendor目录,该目录下包含了当前项目依赖的各个模块的代码。如下:

说明一下:
查询依赖原因
go mod why命令用于解析模块依赖关系,并解释为什么某个模块被包含在项目的依赖项中。如下:

查询依赖结构
go mod graph命令用于生成当前模块的依赖关系图,以展示项目中各个模块之间的依赖关系。如下:

验证依赖完整性
go mod verify命令用于验证当前模块的依赖项的完整性和一致性,它会检查Go Module缓存中当前项目所依赖的各个模块的校验和,与go.sum文件中记录的校验和是否一致,以确保所依赖的模块未被篡改或损坏。如下:

说明一下:
go get命令
go get命令用于下载指定的模块,并将其存放到Go Module缓存中。常用的选项如下:
例如,下面演示了如何通过go get命令获取logrus模块。如下:

说明一下:
go get与go mod download
go get和go mod download命令都用于下载模块,但它们之间存在一些区别。主要区别如下:
go list命令
go list命令用于查询指定模块或go文件的各项信息。常用的选项如下:
例如,下面演示了如何通过go list命令查询logrus模块可用的版本列表。如下:

说明一下: