写在前面
关于 Go Module 的详细资料,可以参考官方的文档。
文章详细地介绍了Go Module的设计以及原理,包含各种命令的使用和 Go 版本的兼容情况。
Go 包管理历史
Go 的包管理大致可以分为3个阶段:GOPATH、vendor、Go Module。
- GOPATH
GOPATH 是 Go 的一个环境变量,程序所依赖的包都放在 GOPATH 下面。一般来讲,GOPATH 默认是用户目录/go,Linux 下是/home/username/go,Windows 下是C:\Users\username\go。目录下要有三个文件夹:
bin:项目编译的二进制文件pkg:项目编译的中间产物,加速编译src:项目源码
在工程经过go build、go install或go get等指令后,会将下载的第三方包源代码文件放在$GOPATH/src目录下, 产生的二进制可执行文件放在 $GOPATH/bin目录下,生成的中间缓存文件会被保存在 $GOPATH/pkg 下。
这种包管理方式在多个项目依赖不同版本的包时存在显而易见的冲突问题,所以出现了 vendor。
- vendor
vendor 意为供应商,在项目目录下新增一个 vendor 文件夹,项目在查找依赖时,将会优先从 vendor 文件夹下查找依赖。使用 go mod vendor命令将会创建当前依赖的副本并存储到$ProjectPath/vendor下。
- Go Module
Go Module 是 Go 11开始支持的包管理方式,如果没有兼容性的考虑,请使用 Go Module 创建项目,而不再使用 Go Path。在 Go Module 的工程下,会存在一个go.mod文件,这是一个模块的描述文件,声明了当前项目是一个 Go Module,并且声明了名字、版本、依赖等信息。同时还会存在一个go.sum文件,这是一个用来保存依赖校验和的文件,防止依赖被篡改。
当开启模块支持时,第 1 部分说的 GOPATH 的意义会发生一点变化。
In module-aware mode,
GOPATHno longer defines the meaning of imports during a build, but it still stores downloaded dependencies (inGOPATH/pkg/mod; see Module cache) and installed commands (inGOPATH/bin, unlessGOBINis set).
也就是说 GOPATH/pkg/mod 会被当做存放下载的依赖的仓库,称为 Module Cache。如果想要清除 Cache,可以使用go clean -modcache删除该目录下的所有已下载的依赖。
模块的使用
如何知道当前 Go 采用怎么样的包管理行为呢?我们可以使用go env命令查看当前的环境变量设置,其中GO11MODULE变量的值决定了Go的包管理行为。
- If
GO111MODULE=off, thegocommand ignoresgo.modfiles and runs inGOPATHmode.- If
GO111MODULE=onor is unset, thegocommand runs in module-aware mode, even when nogo.modfile is present. Not all commands work without ago.modfile: see Module commands outside a module.- If
GO111MODULE=auto, thegocommand runs in module-aware mode if ago.modfile is present in the current directory or any parent directory. In Go 1.15 and lower, this was the default behavior.go modsubcommands andgo installwith a version query run in module-aware mode even if nogo.modfile is present.
简单来说就是,如果关闭模块支持则继续沿用GOPATH的规则;如果开启模块支持,则一律采用Go Module的支持;如果设置为自动,则取决于当前项目根路径下是否存在go.mod文件。
开启
vendor时,go build、go test等命令将只考虑vendor目录下的包,而不再从网络或者module cache下找包。但是
go get、go mod download、go mod tidy等不受影响,还是会下载包到module cache。
常用命令
go mod init: 用来初始化模块go mod tidy: 添加依赖并移除不需要的依赖项go get: 获取依赖,如果不存在将从网络下载,同时更新go.mod的依赖项
使用go get package@version,可以获取指定版本的包。 除了具体的版本,也可以是@master、@latest、@git-tag。 特别的是,使用@none可以移除包依赖。
shell
# Remove a dependency on a module and downgrade modules that require it
# to versions that don't require it.
$ go get golang.org/x/text@none
go get 与 go install
go get会下载依赖,同时更新go.mod文件。- 而
go install则是下载、编译、安装依赖(如果存在Execuables、Programs、Commands也就是main package,则会安装到GOBIN下,否则只是下载到module cache),不会修改go.mod文件。
原本
go get也会编译安装,如果加入-d参数,则不会进行编译安装。而
-d参数在 Go 1.17已经过时,自从 Go 1.18 后,总是默认启用。官方建议使用
go get进行依赖的管理,而使用go install进行可执行文件的安装。
参考资料
1\] [Go Modules Reference](https://link.juejin.cn?target=https%3A%2F%2Fgo.dev%2Fref%2Fmod "https://go.dev/ref/mod") \[2\] [拜拜了,GOPATH君!新版本Golang的包管理入门教程 - 掘金 (juejin.cn)](https://juejin.cn/post/6844903808942735368 "https://juejin.cn/post/6844903808942735368") \[3\] [go mod 使用 - 掘金 (juejin.cn)](https://juejin.cn/post/6844903798658301960 "https://juejin.cn/post/6844903798658301960")