现象
很多人第一次看到 Go 模块的 v2、v3 会觉得别扭:
1module github.com/example/lib/v2
或者:
1import "github.com/example/lib/v2"
为什么版本号还要写进路径?
背后的原因
Go 模块要解决的不只是“依赖哪个版本”,还要保证不同大版本可以共存。
如果 v1 和 v2 的 API 已经不兼容,但 import path 还长得一模一样,编译器和依赖解析器就很难明确知道你到底想用哪个版本。
semantic import versioning 的核心
规则很简单:
v0和v1不需要写进路径v2+必须写进路径
例如:
github.com/example/libgithub.com/example/lib/v2
这样做的好处
最大的好处是“明确”。
一旦 import path 不同:
- 依赖关系更清晰
- 编译期就能区分不同大版本
- 不兼容升级不会悄悄污染旧代码
最容易踩的坑
升到 v2 了,但 module path 没改
这会导致版本发布和实际 import path 不一致,Go 工具链很可能直接报错。
仓库 tag 是 v2,但代码里还是旧路径
这也是典型错误。大版本升级不是只打 tag,还要同步调整模块路径和引用路径。
我的复盘
Go 这里的设计一开始看起来别扭,但本质上是在用路径把“不兼容变更”显式化。长远看,这比把风险藏在版本号里更稳。