在 Go
语言基于 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