依赖管理
Go依赖管理体系的演进:
- GOPATH
- Go Vendor
- Go Module
GOPATH
环境变量$GOPATH通常为~/go。
$GOPATH目录用于存储:
$GOPATH/bin:Go 项目编译产生的二进制文件$GOPATH/pkg:项目编译的中间产物$GOPATH/src:依赖包的源码
这样的设计使得开发环境中所有的项目都依赖$GOPATH/src中的同一份源码,使多个项目依赖一个包时必须依赖同一个版本。
Go Vendor
- 在项目目录下增加
vendor目录,用于存储所有依赖包的副本 - 寻找依赖时,
vendor中的包会被优先使用,如果没有再到$GOPATH/src中寻找
解决GOPATH的问题后,仍然有以下问题:
- 如果该项目依赖的两个包分别又依赖一个包的不同版本,那么无法在
vendor目录中找到合适的版本,因为vendor目录只能为每个包存储一个特定版本。
Go Module
- 通过项目目录下的
go.mod文件管理依赖包版本 - 支持
go get和go mod命令管理依赖包
项目配置文件go.mod
module <module_path>
go <go_version>
require (
<module_path1> <module_version1>
<module_path2> <module_version2>
...
)
第一行定义当前目录下的项目名称<module_path>:
- 本地依赖:
path/to/library - GitHub依赖:
github.com/user_name/repo_name
然后定义Go语言版本<go_version>
依赖项列表:
<module_pathn>为依赖项的名称,和<module_path>格式相同<module_pathn>为依赖项的版本
-
- 版本号允许以下任意一种格式:
-
-
- 语义化版本号:
v{MAJOR}.{MINOR}.{PATCH} - 基于git commit的伪版本:
v{MAJOR}.{MINOR}.{PATCH}-yyyymmddhhmmss-COMMIT_HASH
- 语义化版本号:
-
-
- 其它信息
-
-
// indirect表示该依赖项为间接依赖,是本项目直接依赖项中的某个包依赖的包+incompatible表示没有使用go.mod的旧仓库中的依赖,可能与使用新的依赖系统的包不兼容
-
如果出现两个或多个不同版本的间接依赖项,那么Go会选择其中的最低兼容版本,即同一个{MAJOR}版本中,{MINOR}.{PATCH}最大的版本。
本地命令工具
go get <module_path>下载最新版本,可以添加后缀:
@update默认行为@none删除包@v{MAJOR}.{MINOR}.{PATCH}指定版本@COMMIT_HASH指定commit的伪版本@BRANCH指定分支上的最新commit
go mod
go mod init初始化项目,创建go.mod文件go mod download根据go.mod下载模块到本地缓存go tidy根据代码增加需要的依赖,并删除不需要的依赖
依赖分发
依赖包可能托管在GitHub等平台上,如果每次需要下载依赖时直接访问这些源站,那么可能出现以下问题:
- 无法保证构建稳定性:托管平台上的代码随时可能变动
- 无法保证依赖可用性:作者可能删除包或仓库
- 增加第三方平台压力
为了避免以上问题,Go通过代理服务器(Proxy)下载需要的依赖项,代理服务器会缓存源站上所有注册的包,以及所有的版本,保证依赖项稳定可用。
- 可以通过
${GOPROXY}环境变量配置代理服务器地址,格式为"URL1,URL2,...,direct"(越靠前优先级越高)
-
URLn为一个代理服务器地址direct表示源站