Go 依赖管理变迁:
GOPATH -> go vendor -> go mod
GOPATH:直接将依赖库放在$PATH/src下
- 无法控制依赖版本
- 不同环境下依赖库版本不同
govendor:在项目的vendor中,使用vendor工具更新
- 无法控制依赖版本
go mod:go.mod文件描述了依赖的名称和版本
- 版本的两种表达方式:
- 语义化版本 v M A J O R . {MAJOR}. MAJOR.{MINOR}.${PATCH} MAJOR不同会被认为两个不同的仓库
- 基于某commit的伪版本号 基本版本前缀-commit UTC时间-commit hash前12位
- 两个go mod工具:
- go get example.com/pkg
- go mod tidy:添加或删除项目所需要的依赖
- 版本选择算法:
- 对每个依赖项选择其所被依赖版本中最高的那个版本,如项目依赖A,B,A依赖C 1.1,B依赖C 1.2,则项目会选择C 1.2
- 非理想场景下go mod的问题:
- 【//indirect】标记:表明非项目直接依赖但在本项目中指定该依赖,可能是
- 依赖项没使用go mod
- 不是所有依赖项都在go.mod
- 手动为依赖的依赖指定较新的版本
- 【+incompatible】标记:该依赖未使用go mod管理,依赖的依赖版本, 不影响使用但该依赖的依赖版本没有显示指定,不再认为不同MAJOR号
是不同依赖
两个常用工具:go mod graph, go mod vendor
工程和依赖管理常见问题
-
go get -u xx.xx 后项目编译不通过:这个指令也会把依赖的依赖更新,从而产生不兼容
-
为什么一些工程标记【+incompatible】不使用go mod:有些库在使用 go mod之前就达到v1了,如想拉取最新的库要指定v(x),而该标记不区分MAJOR号,从而可以直接go get拉到最新版本
-
部分项目没有用 go mod 导致某库依赖版本不明确
-
项目依赖依赖A、B,A、B都依赖C(有v1和v2),A、B都没有go mod指定版本:会使用最新版本v2
-
A没有指定版本,B指定了v1:使用v1
-
没有指定版本,B指定了v1:A 想使用v2,则在项目中手动使用indirect指定C的版本依赖
-
依赖库删了tag/branch/commit:更改依赖到最新tag;删除后重新加了同名tag:清理本地缓存
-
循环依赖陷阱:
-
依赖一旦形成,内部全部版本都会保留
-
两个package不能循环依赖但是,两个工程可以互相依赖不同的package
-
临时修改依赖库中的代码测试
clone 仓库到本地 & checkout 对应版本 & replace