Go 1.13+ 中需配置 GOPRIVATE=git.example.com(推荐)或在 go.mod 用 replace,并确保 Git 认证(SSH/HTTPS+PAT)有效、私有包打语义化 tag,CI 中预置凭证并设置 GOPRIVATE。

go.mod 中如何正确声明私有包域名
Go 1.13+ 默认启用 GO111MODULE=on,且对私有域名(如 git.example.com)默认走 proxy(如 proxy.golang.org),但这些域名通常不在公共索引中,直接 go get 会报 unknown revision 或 module not found。
必须在 go.mod 文件顶部显式排除代理,并指定 VCS 源:
replace git.example.com/mylib => git.example.com/mylib v0.1.0
更稳妥的做法是配合 GOPRIVATE 环境变量(推荐):
- 运行
go env -w GOPRIVATE=git.example.com(永久生效) - 或临时设置:
GOPRIVATE=git.example.com go build - 支持通配符:
GOPRIVATE=*.example.com,github.company.com
⚠️ 注意:如果只设 replace 但没配 GOPRIVATE,go list -m all 仍可能失败;反之,只设 GOPRIVATE 而不提供可访问的 Git 服务,go get 会卡在 clone 阶段。
立即学习“go语言免费学习笔记(深入)”;
使用 SSH 还是 HTTPS 克隆私有仓库
Go 的 go get 底层调用 git,因此认证方式完全取决于你本地 git 的配置,而非 Go 工具链本身。
常见组合与问题:
- HTTPS + 个人访问令牌(PAT):需配置
git config --global url."https://token@github.com/".insteadOf "https://github.com/",否则go get会提示 401 - SSH(
git@git.example.com:myorg/mylib):要求~/.ssh/config正确指向私钥,且仓库 URL 必须以git@开头——Go 会自动识别并调用ssh - HTTP Basic Auth(不推荐):URL 中嵌入凭证(
https://user:pass@git.example.com/...)易泄露,且现代 Git 服务器常禁用
验证是否生效:运行 git ls-remote https://git.example.com/myorg/mylib HEAD 或 git ls-remote git@git.example.com:myorg/mylib HEAD,成功返回 commit hash 才算通路正常。
私有包版本控制与伪版本号陷阱
Go 不强制要求私有仓库打 Git tag,但若未打 tag,go mod tidy 会生成类似 v0.0.0-20240520123456-abcdef123456 的伪版本号,其中时间戳基于最新 commit,哈希基于 commit ID。
问题在于:
- 同一 commit 在不同机器上生成的伪版本号一致,但若分支移动、rebase 或 force-push,哈希会变,导致
go.sum校验失败 - CI 构建时若依赖未打 tag 的分支,每次构建可能拉到不同代码,破坏可重现性
建议做法:
- 私有包也遵循语义化版本,打轻量 tag(
git tag v1.2.3)并git push origin v1.2.3 - 开发阶段可用
go get git.example.com/mylib@main显式指定分支,但上线前务必切到 tag - 避免在
go.mod中写死伪版本号(如v0.0.0-...),它只是临时占位符
CI/CD 中私有包认证的最小化配置
GitHub Actions、GitLab CI 等环境无法交互输入密码或加载用户级 SSH 密钥,必须预置凭证。
关键点:
- GitHub Actions:用
GH_TOKEN(repo scope)配合git config替换 URL,或直接用actions/checkout@v4的token参数确保子模块可用 - GitLab CI:将
CI_JOB_TOKEN注入git config,URL 改为https://gitlab.example.com/api/v4/projects/123/repository/archive.zip?sha=...类似路径(需开启 API 访问) - 自建 Git(如 Gitea):推荐用 deploy key 绑定到具体仓库,比用户 token 权限更收敛
别忘了在 CI 脚本开头加 go env -w GOPRIVATE=* 对应域名,否则 go mod download 仍会尝试走 proxy 并超时。
最常被忽略的是:私有包的 go.sum 条目必须和本地一致,而 CI 拉取的是完整模块 zip,不是裸 Git repo——这意味着某些 hook 或 submodule 初始化行为,在 go get 时不会触发,得靠 CI 显式处理。










