必须提交 go.mod 和 go.sum 并统一配置 goproxy 与 goprivate,否则将导致依赖拉取失败、版本不一致、私有模块解析错误;go.sum 是依赖包 sha256 校验快照,缺失则 ci 无法验证完整性;goprivate 必须显式设置以避免私有模块被误判为公开;依赖更新应使用 go get @version 或手动编辑 go.mod + tidy;replace 仅限本地调试,严禁提交;go env -w 配置不自动继承至 docker/ci,需各环境单独固化。

必须提交 go.mod 和 go.sum,并统一配置 GOPROXY 与 GOPRIVATE,否则依赖拉取失败、版本不一致、私有模块解析错误这三类问题会反复出现。
为什么 go.sum 必须进 Git?
它不是“锁文件”,而是所有依赖包内容的 SHA256 校验快照。CI 构建时若缺失或被忽略,go build 仍会下载依赖,但无法验证完整性——攻击者可篡改代理源中的包,而你毫无察觉。
- 常见错误:CI 脚本里执行
go mod download后自动生成go.sum并提交 → 导致本地go test失败,因为校验和不匹配 - 正确做法:开发者本地运行
go mod tidy后,连同生成的go.sum一起提交 - CI 中加一步:
go mod verify,失败即中止构建
GOPRIVATE 漏设是新人最常踩的坑
不设 GOPRIVATE,Go 工具链会把 git.internal.company.com/user-api 当作公开模块,强行走 GOPROXY 查询,结果报错 unknown revision,但根本没提示是代理策略问题。
- 必须用命令固化:
go env -w GOPRIVATE="git.internal.company.com/*" - 检查是否生效:
go env GOPRIVATE输出应为明确路径,不能是空值或off - 多个私有域用逗号分隔:
go env -w GOPRIVATE="git.internal.company.com/*,github.company.net/*"
依赖更新不能靠 go get -u
它无视语义化版本约束,可能把 v1.8.2 直接升到 v2.0.0(即使 go.mod 写着 require example.com/lib v1.8.2),只因 v2 是最新 tag。
- 升级指定版本:
go get example.com/lib@v1.9.0 - 降级或修复漏洞:直接编辑
go.mod中对应行,再跑go mod tidy - CI 中强制校验:
go list -m -u all输出非空时,视为潜在风险,需人工确认
多模块项目里 replace 的使用边界
replace 只应在开发调试阶段临时指向本地路径,绝不能长期存在于主分支的 go.mod 中——它会让 CI 和其他协作者无法复现构建环境。
- 正确用法:仅在本地
go.mod文件末尾加replace,且该行不提交;或通过GOFLAGS="-mod=readonly"阻止 CI 执行 replace - 子模块发布后,立刻删掉
replace,改用真实版本号:require modules/user v0.5.1 - 跨模块共享工具包(如
internal/util)不应拆成独立模块,避免replace泛滥
真正容易被忽略的,是 go env -w 设置的环境变量不会自动继承到 Docker 构建上下文或远程 CI agent 中——每个环节都得单独固化,不能只靠本地 shell 配置。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











