这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
Go语言包依赖发展阶段:
GOPATH: 安装时需要指定的go语言工作区
- bin : 项目编译出的二进制文件
- pkg : 项目编译的中间产物, 加速编译
- src : 项目源码
缺点: 无法解决多版本依赖问题
Vendor: 在项目目录下添加vendor文件夹, 将所有依赖包按项目组织, 类似于node_modules 缺点: 依然无法解决多依赖, PackageB依赖PackageD的v1版本, PackageC依赖PackageD的v2版本, 此时会出现依赖冲突
Go Module 当前的解决方案, go 1.11 引入
- 通过 go.mod 文件管理依赖包版本
- 通过 go get/go mod 指令管理依赖包 依赖管理三要素
- 配置文件, 描述依赖 go.mod
- 中心仓库管理依赖库 proxy
- 本地工具 go get/mod
以一个具体的go.mod文件为例
module example/project/app // 模块名, 每个模块作为依赖管理的基本单元
go 1.16 // 使用go的版本
require (
example/lib1 v1.0.2
// 每个依赖由 module name + version code 组成, 如果是间接依赖会用 indirect 标识.
)
版本号规则
- 语义化版本
${Major}.${Minor}.${Patch}
基于git tag功能发版, Major代表一个大的版本更新, 不同大版本前后直接可能不兼容, Minor为小版本, 代表不同版本间的迭代, Patch为提交版本, 既每次提交打包会在流水线上自增一个新版本.
由于大版本直接可能不兼容, 第一个大版本后面的版本的代码路径会添加当前的版本号, 比如
my/pkg/xxx=>my/pkg/v2/xxx - 基于commit伪版本 vx.0.0-yyyymmddhhmmss-abcdefgh1234 对于没有语义化版本的库, go自动为每个提交生成一个版本, 规则为语义化版本+提交时间戳+提交id
为了解决代码仓库(github)上的代码不稳定的问题(被修改, 代码被删除等等), 提出proxy机制, 通过定义GOPROXY环境变量设置, 在拉取代码前, 会首先通过proxy网站获取. proxy网站就类似于java中的maven central或npm的npm registry, 但不是中心化的, 用户需要自己选用proxy网站.
同时本地使用go.sum文件, 保存依赖项目的hash值, 避免依赖项目在版本号不变的情况下变更, 导致编译失败.
go.mod 如何解决依赖冲突? 最大版本选择规则. 既对相同项目出现多个不同版本的依赖时(深度优先遍历扫描所有依赖), 选择同一大版本下最高的次版本. go mod 的依赖源码会保存在$GOPATH/pkg/mod目录下, 并会针对同一项目的不同版本号分别存错