Go 语言基于 modules 的包管理系统中,默认的包版本号都是 v0.*v1.* 系列,以 0 开头的表示 beta 版本,而 1.* 系列表示稳定版本。

然而有些时候我们有希望命名包版本为号为 v2+ 以上的版本需求,比如项目被整体重构的时候。如果需要构建版本号为 v2.*及以上的版本号时,官方建议是新建子目录方式来实现,即在当前项目目录下新建一个主版本号子目录,我们以 github.com/apptut/go-labs 项目为例:

该项目目前已经存在一个主版本模块:

  1. # go-labs
  2. ├── go.mod
  3. ├── go.sum
  4. ├── hotload
  5. └── strings

并且已经存在一个主模块,我们查看 go.mod 文件:

  1. cat go.mod
  2. module github.com/apptut/go-labs
  3. # ... 后续省略

1.初始化子模块

我们再此目录下新建一个 v2 子目录:

  1. # 新建 v2系列版本
  2. mkdir v2

并且我们还需要重新初始化 v2 版本目录下的所有代码规划,为了省事我们可以直接拷贝原有父级目录代码到该目录下:

  1. cp -r hotload strings v2/

接下来还需要重新初始化 v2 版本的 go.mod 文件:

  1. cp go.mod v2/go.mod
  2. go mod edit -module module github.com/apptut/go-labs v2/go.mod

2. 解决依赖

经过步骤一后,我们还需要检查代码中的依赖包问题,如果在你的包中,有相互依赖的子包,请记得一定要更新代码依赖版本为 v2 版本系列,例如在 go-labs 项目中有代码存在如下依赖,我们也需要一并替换成 v2 版本:

  1. // import "github.com/apptut/go-labs/hotload/inotify/watcher"
  2. import "github.com/apptut/go-labs/v2/hotload/inotify/watcher"

当然你可以使用 find 命令进行批量查找替换,如官方给出的参考示例:

$ find . -type f \
    -name '*.go' \
    -exec sed -i -e 's,github.com/my/project,github.com/my/project/v2,g' {} \;

3. 添加版本号

基本上经过如上两个环节,代码准备阶段大功告成,剩下的便是添加仓库版本号即可:

$ git tag v2.0.0
$ git push origin v2.0.0

操作完成后,你可以使用 go get 命令测试,是否升级成功:

go get -x github.com/apptut/go-labs/v2

额外说明

子目录版本好处

官方建议使用子目录方式扩展版本号,好处是可以兼容基于 GOPATH 方式开发的项目。且相比于分支方式建立版本号,子目录可以明确知道当前使用的版本,如果是分支形式,尤其是当前master分支,很难表达是哪个具体分支。

.v2 和 /v2 区别

此外,你可能还看到过如有类似后缀的版本号包: gopkg.in/yaml.v2.v2 为后缀的版本, Go 语言也支持,但是这个仅仅支持 gopkg.in 域名下,如果你是自建的模块,那么这种方式是不支持的,放在 github 也白搭,所以老老实实写成: /v2 形式吧。

v2+版本包缓存树

版本升级到 v2+ 以上后,本地模块包缓存的目录结果也发生了变化,多了一层主版本号父级目录:

➜  test cd ~/go/pkg/mod/cache/download/github.com/apptut/go-labs
➜  go-labs tree
.
├── @v
│   ├── v0.0.0-20201009072358-9955584358ef.info
│   ├── v0.0.0-20201009072358-9955584358ef.lock
│   ├── v0.0.0-20201009072358-9955584358ef.zip
│   └── v0.0.0-20201009072358-9955584358ef.ziphash
└── v2
    └── @v
        ├── list
        ├── list.lock
        ├── v2.0.1.info
        ├── v2.0.1.lock
        ├── v2.0.1.mod
        ├── v2.0.1.zip
        └── v2.0.1.ziphash