唯一正确路径是用 go mod 管理依赖:模块路径须用真实托管域名前缀(如 example.com/myapp),初始化前清理残留,go get @vX.Y.Z 不锁定版本需手动编辑 go.mod 并 tidy,go.sum 必提交且不可忽略,replace/exclude 仅临时使用且上线前必须移除。

直接用 go mod,别碰 vendor 或旧工具——这是唯一能避免 CI 报错、本地构建不一致、依赖悄悄升级的路径。
初始化模块时 module path 写错就全盘被动
模块路径不是“随便起个名”,它决定了所有 import 语句和下游引用方式。写成 github.com/yourname/project 看似合理,但如果你项目实际托管在 gitlab.example.com/group/app,后续换源、打 tag、别人 go get 都会出问题。
- 推荐做法:用公司或个人域名前缀,比如
example.com/myapp(无需真实可访问) - 绝对避免:
main、.、./local这类非法路径,go build会直接报错 - 初始化前先清理残留:
rm -f go.mod go.sum Gopkg.lock vendor/,否则go mod init可能推断出错误路径 - 初始化后立刻检查
go.mod第一行是否为你写的路径,不是就手动改,再跑一次go mod tidy
go get @vX.Y.Z 不生效?本质是没理解它的“升级”逻辑
go get github.com/sirupsen/logrus@v1.9.3 不等于“锁定 v1.9.3”,而是“尝试升级到满足约束的 v1.9.3 或更高 patch 版本”。如果当前已存在 v2.0.0+incompatible,它可能拒绝降级;如果 tag 不存在或 proxy 缓存未命中,它 fallback 到 latest 并只 warn。
- 要真正锁定:编辑
go.mod,手动写require github.com/sirupsen/logrus v1.9.3,再执行go mod tidy - 验证 tag 是否存在:
curl -I https://proxy.golang.org/github.com/sirupsen/logrus/@v/v1.9.3.info - 临时绕过版本限制:用 commit hash,如
go get github.com/sirupsen/logrus@55046e2 - 禁止自动升级:别用
go get -u,改用go mod edit -require=...+go mod tidy
go.sum 被修改不是“出错了”,而是校验机制在工作
go.sum 不是锁文件,是每个模块内容的哈希快照。只要远程包内容变了(比如 tag 被强制重写、你换了 GOPROXY 源、CI 和本地用不同网络环境),go.sum 就必须更新——否则 go build 直接失败,报 checksum mismatch。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
-
go.sum必须提交进 Git,不能 ignore - CI 中禁止运行
go mod download后再提交新go.sum,这会让本地开发者拉代码后校验失败 - 若遇到校验失败,先确认是不是代理源差异导致——比如本地用
https://goproxy.cn,CI 用https://proxy.golang.org - 不要设
GOSUMDB=off来跳过校验,这等于主动放弃防篡改能力
replace 和 exclude 不是常规手段,是临时止血方案
replace 常用于本地调试 fork 或未发版的修改,exclude 仅限严重漏洞且上游无修复时临时规避。两者共存时顺序敏感,且一旦提交到主干,就会污染整个团队的构建环境。
-
replace后必须加go mod tidy,否则不会生效 - 私有库替换推荐写法:
replace github.com/org/lib => git.example.com/org/lib v1.2.0,而非指向本地路径(CI 构建会失败) -
exclude会导致依赖图不完整,go list -m all查不到被排除的模块,排查问题时容易漏掉源头 - 上线前务必删掉
replace和exclude,改用正式发布的 tagged 版本
最易被忽略的点:模块路径一旦发布 v1.x,就不能改;tag 必须带 v 前缀(v1.2.3),否则 go get @latest 会 fallback 到不可追溯的伪版本。

















