go mod 版本依赖问题
Go module遵循语义化版本规范 2.0.0 major.minor.patch
样板分析
1. model path
一行是module path, 一般采用仓库地址方式定义。这样我们获取一个module的时候,就可以到它的仓库中去查询,或者让go proxy到仓库中去查询。
如果版本大于2.0.0,按照规范,需要加上major后缀,比如加上v2,v3,以便和其它major版本进行区分。
// 不同tag, module名不一样 module githup.com/panicthis/modfile/v2
这样 go mod 通过不同的major版本,让他们共存,也就是识别成独立的包
2.go directive
第二行是go directive,不是指你当前使用的Go版本,而是指名你的代码所需要的Go的最低版本
go 1.16
3.require
require段中列出了项目所需要的各个依赖库以及它们的版本,除了正规的v1.3.0这样的版本外
4.incompatible
这些库采用了go.mod的管理,但是不幸的是,虽然这些库的版major版本已经大于等于2了,但是他们的module path中依然没有添加v2、v3这样的后缀。
标记为不规范,这样不同major版本,共存也就失效了, go mod 会选择最新版本,因为默认是新版本是兼容旧版本的。
5.包依赖冲突的问题
- major 特性:包同时共存。在Go中,由于采用语义导入版本机制,major版本号不同的module被视为不同的module,即使它们源于同一个repository(比如上面的源于同一个P3的v1.5和v2.0就被视为两个不同的module)。
当然这种解决方案是有代价的!第一个代价就是构建出来的app的二进制文件size变大了,因为二进制文件中包含了多个版本的P3的代码;第二个代价,可能也算不上代价,更多是要注意的是不同版本的module之间的类型、变量、标识符不能混用,我们以go-redis/redis这个开源项目举个例子。go-redis/redis最新大版本为v8.11.4,没有启用go.mod时的版本为v6.x.x,我们将这两个版本混用在一起。
2)历史遗留问题,有些项目没有使用go mod 模式,所以项目中go.mod文件,
那么不同major的包共存特性也就没有,如果同时引用的话,那么会选择最新的版本。