一直以来,直接git打tag就可以发布新版本。
但是今天,在发布v2以上版本时遇到了一些问题,记录一下。
文中实际module路径均以github.com/abc/hello代替。

还是按照老方法,直接git打tag,发布。结果在调用方就出现了问题。

更新go mod时直接报错:

require github.com/abc/hello: version “v2.x.x” invalid: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2

我找到一种解决方法是,调用方在go.mod,import这个module时,版本号后面加+incompatible

1
import github.com/abc/hello v2.0.0+incompatible

这样的缺点是,不太正式(仅仅是module发布者没有支持go module时,调用者可以采用的补丁方案)。
而且无法做到在一个项目中同时import同一个module的多个版本。

同时一些IDE可能由于不识别这种版本号标识而报错。

如果我们仅仅是module的调用者而非编写者,而实际编写者又没有支持go module时,我们就可以使用这种方案临时解决调用问题。


而我们作为module的编写者,更完美的解决方案是:

在module编写方,将go.mod中的moulde名称后面增加版本号/vx


module github.com/abc/hello
->
module github.com/abc/hello/v2

注意,项目文件的实际结构不需要做任何改变,不需要建立v2或者vn文件夹,仅仅用于go module识别主版本号。

而后重新在git中打tag v2.x.x,发布

调用方就可以愉快地使用了。
调用方的注意事项:

  1. go.mod中需要对应修改require path
    require github.com/abc/hello/v2 v2.x.x
  2. 代码中对应修改import path
    import github.com/abc/hello/v2

这样的好处,module发布者根据go module特性处理了版本问题。

同时调用者可以import同一模块的多个主版本。
由golang采用的语义化版本号(Semantic Versioning)可知,同一主版本向下兼容,因此每个主版本一份完全满足需求。

1
2
3
4
5
require (
github.com/abc/hello v1.x.x
github.com/abc/hello/v2 v2.x.x
github.com/abc/hello/v3 v3.x.x
)
1
import "github.com/abc/hello"
1
import "github.com/abc/hello/v2"
1
import "github.com/abc/hello/v3"

v0和v1似乎还是只能导入一个。
不过在语义化版本号中,v0代表试验的初期不稳定版本,有了v1就基本不会再有用v0的需求,问题不大。