用 go module 的 replace + 私有仓库 + 语义化版本发布是多团队共用 github.com/org/common 包最可控方案;需在各团队 go.mod 中 replace 指向内部 git 地址并带 vx.y.z 版本,上线前必须删 replace 改用 require,且公共包 module 名须与路径严格一致。

Go模块如何让多个团队共用一个github.com/org/common包
直接结论:用 Go Module 的 replace + 私有仓库 + 语义化版本发布,是目前最可控、最易落地的方案。不是靠 GOPROXY 全局代理,也不是靠本地 go mod edit -replace 临时硬编码。
核心在于:每个团队的 go.mod 文件里明确声明对公共包的依赖版本,并在 CI 或开发机上通过 replace 指向内部 Git 地址(如 git.internal.org/org/common),同时确保该仓库支持 go get 直接拉取——即开启 Go Module 支持、打带 vX.Y.Z 前缀的 tag、提供 go.mod 文件。
- 不要把公共包放在各团队项目目录下用
replace ./common—— 这会导致构建不可复现、CI 失败、无法跨团队同步更新 - 不要用
go mod vendor把公共包打进各项目 —— 版本分散、升级成本高、安全补丁难统一推送 - 必须要求公共包自身
go.mod中module名与导入路径严格一致(例如module github.com/org/common),否则go get会报mismatched module path
为什么 go get github.com/org/common@v1.2.0 在公司内网会失败
现象是:本地能 go get,但 CI 流水线或新同事机器上提示 unknown revision v1.2.0 或 cannot find module providing package。本质是 Go 默认只信任 HTTPS 公网 Git 服务,而你的私有仓库可能走 HTTP、SSH、或自建 Gitea/GitLab 且未配置 GOPROXY 兼容接口。
- 确认私有 Git 服务是否支持
/@v/list和/@v/v1.2.0.info等 Go Module API(Gitea ≥1.16、GitLab ≥15.6 原生支持;老旧版本需反向代理补全) - 在团队共用的
.netrc或git config --global url."https://git.internal.org/".insteadOf "https://github.com/"配置重写规则 - CI 中显式设置
export GOPRIVATE=github.com/org/common(注意不是*,避免误伤其他私有依赖) - 若用 SSH 路径(如
git@git.internal.org:org/common.git),需确保go命令能走 SSH 认证 —— 推荐改用 HTTPS + token 方式更稳定
replace 在 go.mod 里怎么写才不踩坑
replace 是开发阶段绕过网络限制、验证兼容性的关键手段,但它不是长期依赖声明方式。它的作用域仅限当前模块,且不会传递给下游依赖者 —— 这既是优点(隔离影响),也是陷阱(别人没法自动继承)。
- 正确写法:
replace github.com/org/common => git.internal.org/org/common v1.2.0
(注意末尾是版本号,不是分支名) - 错误写法:
replace github.com/org/common => ./common(路径相对当前go.mod,CI 构建时路径不存在) - 错误写法:
replace github.com/org/common => git.internal.org/org/common master(master 不是有效版本,go build会忽略该 replace) - 上线前必须删掉
replace行,改用require github.com/org/common v1.2.0—— 否则其他团队引用你项目时,无法解析出真实依赖
多团队版本冲突时,谁该升级?怎么升?
常见场景:Team A 用 v1.2.0,Team B 已升级到 v1.3.0 并加了新函数,Team A go build 报错说找不到该函数。这不是 Go 模块的问题,是协作流程缺失。
- 公共包每次 break change 必须发大版本(
v2.0.0),并变更module名为github.com/org/common/v2,老版本继续维护 - 禁止在
v1.x系列里删函数、改签名、动导出变量类型 —— 这类修改必须进v2 - 建议在公共包 CI 中加入「兼容性检查」:用
gofork或stdlib的go vet -vettool=... -composers扫描导出符号变化 - 升级动作应由使用方发起(不是公共包团队强制推送),升级 PR 必须包含:更新
go.mod、跑通所有测试、检查是否有新增必填字段或行为变更
最难的不是技术配置,而是让所有团队接受「公共包不是你家的,你改了就得通知所有人」这个事实。版本号不是数字游戏,是契约。











