Go模块v2+必须在module路径末尾显式添加/v2后缀,如module github.com/user/repo/v2,否则go mod tidy或go build会报错;导入路径也须完全一致,且需打v2.0.0等SemVer tag。
/v2 后缀,否则直接报错Go 从 v1.11 起强制要求:主版本号 ≥ 2 的模块,其 module 声明路径末尾**必须显式包含 /vN(如 /v2、/v3)**。这不是可选项,而是模块系统识别“新主版本”的唯一依据。不加后缀会导致 go mod tidy 或 go build 失败,并抛出类似错误:
invalid version: module contains a go.mod file, so major version must be compatible
这个限制的底层逻辑是:Go 把 github.com/user/repo 和 github.com/user/repo/v2 视为两个完全独立的模块,可以共存、互不干扰。这也是 Go 实现“多主版本并行维护”的基础机制。
module github.com/user/repo/v2
module github.com/user/repo(即使你已打 v2.0.0 tag)v0 和 v1 不需要后缀(v1 是隐式默认),但一旦升到 v2,就必须改路径go.mod 中的 module 完全一致调用方写 import "github.com/user/repo/v2",和你的 go.mod 里声明的 module github.com/user/repo/v2 必须一字不差——包括大小写、斜杠位置、有无 v2。任何不一致都会导致构建失败或无法解析依赖。
github.com/user/repo/v2,就**不能**在代码里写 import "github.com/user/repo" 或 import "github.com/user/repo/v2.0"
github.com/user/repo/utils 需改为 github.com/user/repo/v2/utils
go mod tidy 会自动修正本地 import 路径,但只对当前模块生效;跨模块引用仍需手动检查Go 的“版本分支”不是 Git 分支概念,而是一套基于语义化版本(SemVer)+ 路径后缀的发布协议。你不需要为 v2 单独建 release/v2 分支(虽然可以这么做便于开发隔离),但**必须打带 v 前缀的 tag**,例如:
git tag v2.0.0 —— 主版本升级,含不兼容变更git tag v2.1.0 —— 新增向下兼容功能git tag v2.1.1 —— 仅修复 bug,不改 API这些 tag 必须推送到远程:git push origin v2.0.0。其他项目执行 go get github.com/user/repo/v2@v2.1.0 才能拉到对应版本。没有 tag,go 工具链只会 fallback 到伪版本(v0.0.0-...),不可靠。
实际迁移中,最容易翻车的是路径残留和环境配置缺失:
import "github.com/user/repo",没改成 /v2 → 编译失败或静默使用 v1go.mod 里 require 仍指向 v1 路径,go mod tidy 没清干净 → 构建时可能拉错版本GOPRIVATE → go get 会尝试走 proxy.golang.org,超时或 403GOPRIVATE → 测试通过,上线却拉不到私有 v2 模块最稳妥的做法是:改完 go.mod 和所有 import,运行 go mod tidy -v 查看是否还有旧路径残留,再用 go list -m all | grep repo 确认最终解析的模块路径和版本。