学习Go Module 构建模式¶
概要: 全面拥抱 Go Module 构建模式
创建时间: 2022.08.24 21:30:37
更新时间: 2023.08.16 22:27:21
GOPATH 模式¶
下面假定使用的 go 语言版本为 1.18
Go | |
---|---|
go build main.go
时,Go 编译器在 GOPATH 构建模式下会搜索第三方包 github.com/sirupsen/logrus
路径搜索
如果配置了如下的 GOPATH
Bash | |
---|---|
Bash | |
---|---|
提示
GOPATH如果没有配置,默认路径为 $HOME/go
安装缺失的包
Bash | |
---|---|
/usr/local/golang/src/github.com/sirupsen/logrus
弊端¶
go get 下载的包只是当前时刻各个依赖包的最新主线版本,也就是说不同人在不同时刻运行此命令获得的包可能并不完全一致,这样可能导致兼容性等方面的问题。
总结¶
在 GOPATH 构建模式下,Go 编译器实质上并没有关注 Go 项目所依赖的第三方包的版本。
vendor 模式¶
Go 在 1.5 版本中引入 vendor 机制。vendor 机制本质上就是在 Go 项目的某个特定目录下,将项目的所有依赖包缓存起来,这个特定目录名就是 vendor
对于上面一节的例子,添加vendor目录后,缓存第三方包后结构如下:
弊端¶
如果依赖的包很多,将导致自己的项目库体积显著变大,影响拉取等操作。此外更致命的是,手动管理vendor下的依赖包版本十分头疼,包括项目依赖包的分析、版本的记录、依赖包获取和存放。
总结¶
十分鸡肋
Go Module 模式¶
从 Go 1.11 版本开始,除了 GOPATH 构建模式外,Go 又增加了一种 Go Module 构建模式。
Go Module是什么¶
- 一个 Go Module 是一个 Go 包的集合,它包含了包的版本号信息。
- 通常情况下,一个代码仓库对应一个 Go Module ,即在项目的根目录下放置
go.mod
文件,Go Module 与go.mod
是一一对应的。 go.mod
文件所在的顶层目录也被称为 module 的根目录,module 根目录以及它子目录下的所有 Go 包均归属于这个 Go Module,这个 module 也被称为 main module。
Go Module使用方法¶
go mod init "my/pkg/name"
创建 go.mod 文件go mod tidy
自动更新当前项目的依赖包信息go build my_pkg.go
构建自己的module
下面以第一节的项目为例,在 go 1.18 环境下演示使用方法。
创建 go.mod¶
Bash | |
---|---|


查看
go.mod
内容如下
更新 go.mod¶
Bash | |
---|---|

再次查看
go.mod
内容如下
Bash | |
---|---|
github.com/sirupsen/logrus
的依赖包
构建 module¶
Bash | |
---|---|

Go Module版本机制¶
- 按照语义版本规范,主版本号不同的两个版本是相互不兼容的
- 主版本号相同时,次版本号大都是向后兼容次版本号小的版本。补丁版本号也不影响兼容性
语义导入版本机制¶
不同主版本号的导入方式不同,对于 0.x.y
和 1.x.y
的包,导入时不需要带上额外版本说明,高于1时,导入方式为 import "github.com/sirupsen/logrus/v2"
最小版本选择机制¶
如果自己的包同时依赖 A(v1.1.2) 和 B(v1.2.4) 两个包,且 A 包依赖 C(v1.3.0),B 包也依赖 C(v1.4.0),但 C 包最新版为 v1.8.0。
Go 设计者在诸多兼容性版本间,他们不光要考虑最新最大的稳定与安全,还要尊重各个 module 的述求:A 明明说只要求 C v1.1.0,B 明明说只要求 C v1.3.0。所以 Go 会在该项目依赖项的所有版本中,选出符合项目整体要求的“最小版本”。
所以,go会选择 C(v1.4.0),因为此版本是符合项目整体要求的版本集合中的版本最小的那个。
展望¶
Go 核心团队已经考虑在后续版本中彻底移除 GOPATH 构建模式,Go Module 构建模式将成为 Go 语言唯一的标准构建模式。
总结¶
抛弃 GOPATH 和 vendor 构建模式,全面转向 Go Module 构建模式。