1. 简介
Go module的版本选择机制,其中介绍了一个Module的版本号需要遵循v<major>.<minor>.<patch>
的格式,此外,如果major版本号大于1时,其版本号还需要体现在Module名字中。
比如Module github.com/RainbowMango/m
,如果其版本号增长到v2.x.x
时,其Module名字也需要相应的改变为:github.com/RainbowMango/m/v2
。即,如果major版本号大于1时,需要在Module名字中体现版本。
那么如果Module的major版本号虽然变成了v2.x.x,但Module名字仍保持原样会怎么样呢? 其他项目是否还可以引用呢?其他项目引用时有没有风险呢?这就是今天要讨论的内容。
2.能否引起不兼容的包
以以Module github.com/RainbowMango/m
为例,假如其当前版本为v3.6.0
,因为其Module名字未遵循Golang所推荐的风格,即Module
名中附带版本信息,我们称这个Module为不规范的Module。
不规范的Module还是可以引用的,但跟引用规范的Module略有差别。
如果我们在项目A中引用了该module,使用命令go mod tidy
,go 命令会自动查找Module m的最新版本,即v3.6.0。
由于Module为不规范的Module,为了加以区分,go 命令会在go.mod
中增加+incompatible
表示
require (
github.com/RainbowMango/m v3.6.0+incompatible
)
除了增加+incompatible(不兼容)
标识外,在其使用上没有区别。
3.如何处理incompatible
go.mod文件中出现+incompatible
,说明你引用了一个不规范的Module,正常情况下,只能说明这个Module版本未遵循版本化语义规范。但引用这个规范的Module还是有些困扰,可能还会有一定的风险。
比如,我们拿某开源Module
github.com/blang/semver
为例,编写本文时,该Module最新版本为v3.6.0,但其go.mod
中记录的Module却是:
module github.com/blang/semver
Module github.com/blang/semver
在另一个著名的开源软件Kubernetes(github.com/kubernetes/kubernetes)
中被引用,那么Kubernetes
的go.mod
文件则会标记这个Module为+incompatible
:
require (
...
github.com/blang/semver v3.5.0+incompatible // 添加了额外的表示
...
)
站在Kubernetes
的角度,此处的困扰在于,如果将来 github.com/blang/semver
发布了新版本v4.0.0
,但不幸的是Module名字仍然为github.com/blang/semver
。那么,升级这个Module的版本将会变得困难。因为v3.6.0
到v4.0.0
跨越了大版本,按照语义化版本规范来解释说明发生了不兼容的改变,即然不兼容,项目维护者有必须对升级持谨慎态度,甚至放弃升级。
站在github.com/blang/semver
的角度,如果迟迟不能将自身变得”规范”,那么其他项目有可能放弃本Module,转而使用其他更规范的Module来替代,开源项目如果没有使用者,也就走到了尽头。