Go中包版本号v2+设计

二维码
| Oct 09, 2020 | 原创

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

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

该项目目前已经存在一个主版本模块,原有代码如下:

# go-labs
├── go.mod
├── go.sum
├── hotload
└── strings

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

cat go.mod

module github.com/apptut/go-labs

# ... 后续省略

1.初始化子模块

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

# 新建 v2系列版本
mkdir v2

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

cp -r hotload strings v2/

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

cp go.mod v2/go.mod

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

2. 解决依赖

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

// import "github.com/apptut/go-labs/hotload/inotify/watcher" 
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