go111module=on是硬性前提,否则go mod命令失效、项目fallback至gopath模式;需配合goprivate显式声明私有域名、go mod init使用完整模块路径,并统一配置避免依赖链断裂。

GO111MODULE=on 是硬性前提,不是可选项
不设这个,go mod 命令压根不生效,项目会 fallback 到 GOPATH 模式,私有库根本进不了依赖图。很多团队在 CI 环境里踩坑,就是因为镜像里还沿用 GO111MODULE=auto —— 它靠路径猜模块,/tmp 或 /home/ci/project 这类路径直接被判定为非模块目录,go mod init 生成的 go.mod 会被忽略。
执行这条命令一次就够了:go env -w GO111MODULE=on
- 别写成
export GO111MODULE=on放 shell profile 里——容易被子进程覆盖或遗忘 reload - CI 脚本开头必须加这句,尤其用 alpine 或旧版 golang:1.15 镜像时
- 验证方式:
go env GO111MODULE输出必须是on,不是auto
GOPRIVATE 必须显式声明私有域名,不能靠代理跳过
只配 GOPROXY 不配 GOPRIVATE,Go 仍会把 git.internal.company.com/lib/auth 当作公共模块去代理拉取,结果就是 401 或 404,报错信息里带 reading git.internal.company.com/lib/auth/go.mod: 401 Unauthorized。
正确做法是明确告诉 Go:“这些域名下的模块,一律不走代理,直接走 git 协议”:go env -w GOPRIVATE="git.internal.company.com,github.com/myorg"
- 支持通配符:
go env -w GOPRIVATE="*.internal.company.com" - 多个域名用逗号分隔,**不能有空格**
- 如果用 SSH 地址(如
git@company.com:lib/auth.git),域名部分仍要填company.com - 本地开发时,若私有库用 file:// 路径,也得加进去,比如
go env -w GOPRIVATE="file://*"
私有模块发布前必须确保 go.mod module 路径与实际 Git 地址一致
模块路径不是随便起的。假设你的私有库 Git 地址是 https://git.internal.company.com/libs/logging,那它的 go.mod 第一行必须是:module git.internal.company.com/libs/logging
否则下游项目 require git.internal.company.com/libs/logging v0.3.1 时,Go 会去代理或 Git 服务器上找这个路径,而实际仓库地址对不上,就拉不到代码。
- 初始化命令要用完整路径:
go mod init git.internal.company.com/libs/logging - 不要用
go mod init logging再手动改 ——go mod tidy后可能被重写回错误路径 - Tag 版本(如
v0.3.1)必须对应 Git commit,且该 commit 下的go.mod路径不变 - 如果团队用自建 Artifactory 或 Gitea,确认其 Go Registry 功能已启用,并返回正确的 module path header
团队内统一配置 .gitignore 和 go.mod 生成规则
开发者本地手动生成 go.mod 时,常因路径错误导致 module 名混乱。比如在 ~/work/myapp 下运行 go mod init myapp,结果路径变成 myapp,但公司规范要求所有模块路径以 company.com/ 开头。
解决方案是提供标准化脚本或模板:echo "module company.com/project/myapp" > go.modecho "go 1.21" >> go.modgo mod tidy
-
.gitignore必须排除/vendor(除非明确启用 vendor 模式),否则go mod tidy -v清理不干净 - 禁止手动编辑
require行 —— 所有依赖增删都走go get或go mod edit - CI 构建前加校验:
grep -q "^module company.com/" go.mod || exit 1 - 私有模块的
go.sum文件应提交到 Git,避免不同人本地缓存不一致
最难的不是配置本身,而是让所有人执行同一套规则。最常被忽略的是 GOPRIVATE 的通配符写法和 go mod init 时的 module 路径一致性 —— 这两点出错,整个私有依赖链就断在第一步。











