升级module的major版本号

升级module的major版本号

升级module的major版本号 #

Go Module 的语义导入版本机制规定:如果同一个包的新旧版本是兼容的,那么它们的包导入路径应该是相同的。反过来说,如果新旧两个包不兼容,那么应该采用不同的导入路径。

而且,我们知道,Go 团队采用了将“major 版本”作为导入路径的一部分的设计。这种设计支持在同一个项目中,导入同一个 repo 下的不同 major 版本的 module,比如:

import (
    "bitbucket.org/bigwhite/m1/pkg1"   // 导入major版本号为v0或v1的module下的pkg1
    pkg1v2 "bitbucket.org/bigwhite/m1/v2/pkg1" // 导入major版本号为v2的module下的pkg1
)

在同一个 repo 下,不同 major 号的 module 就是完全不同的 module,甚至同一 repo 下,不同 major 号的 module 可以相互导入。

这样一来,对于 module 作者 / 维护者而言,升级 major 版本号,也就意味着高版本的代码要与低版本的代码彻底分开维护,通常 Go 社区会采用为新的 major 版本建立新的 major 分支的方式,来将不同 major 版本的代码分离开,这种方案被称为“major branch”的方案。

major branch 方案对于多数 gopher 来说,是一个过渡比较自然的方案,它通过建立 vN 分支并基于 vN 分支打 vN.x.x 的 tag 的方式,做 major 版本的发布。

那么,采用这种方案的 Go Module 作者升级 major 版本号时要怎么操作呢?我们以将 bitbucket.org/bigwhite/m1 的 major 版本号升级到 v2 为例。

  1. 建立 v2 代码分支并切换到 v2 分支上操作。
  2. 修改 go.mod 文件中的 module path,增加 v2 后缀。
//go.mod
module bitbucket.org/bigwhite/m1/v2

go 1.17

如果 module 内部包间有相互导入,那么在升级 major 号的时候,这些包的 import 路径上也要增加 v2,否则,就会存在在高 major 号的 module 代码中,引用低 major 号的 module 代码的情况,这也是 module 作者最容易忽略的事情。

这样一通操作后,我们就将 repo 下的 module 分为了两个 module 了,一个是原先的 v0/v1 module,在 master/main 分支上;新建的 v2 分支承载了 major 号为 2 的 module 的代码。

对于消费者而言,在它依赖的 module 进行 major 版本号升级后,他们只需要在这个依赖 module 的 import 路径的后面,增加 /vN 就可以了(这里是 /v2),当然代码中也要针对不兼容的部分进行修改,然后 go 工具就会自动下载相关 module。

Viewpoint #

From #

加餐|作为Go Module的作者,你应该知道的几件事