go mod download 默认只下载直接依赖,不下载间接依赖;要下载全部依赖需用 go mod download all,它等价于 go list -m all | xargs go mod download,覆盖完整模块图但忽略 replace 到本地路径和 vendor 内模块。

go mod download 会下载哪些模块
go mod download 默认只下载当前模块的直接依赖(go.sum 中列出的、且 go.mod 里声明的那些),不会递归拉取间接依赖的源码——除非它们被显式引用或触发了构建。也就是说,它不等价于“把整个依赖树都下全”。常见误解是以为运行一次就万事大吉,结果 go build 时仍要联网拉某些 indirect 模块。
- 执行前确保
go.mod是最新的(必要时先go mod tidy) - 若想强制下载全部依赖(含 indirect),加
-x参数看实际 fetch 行为,再配合go list -m all手动展开 - CI 环境中建议用
go mod download all(注意:这里的all是特殊关键字,不是通配符)
go mod download all 的真实行为
go mod download all 是唯一能覆盖完整模块图的方式,它等价于 go list -m all | xargs go mod download,会把所有出现在 go list -m all 输出里的模块都下到本地 $GOPATH/pkg/mod 缓存中。但要注意:all 不包含 vendor 内模块,也不处理 replace 后指向本地路径的模块(它们本就不需要下载)。
- 该命令不检查代码是否可编译,只管下载;哪怕某个模块在
go.mod里被exclude了,只要go list -m all还能列出来,它就会下 - 下载过程无进度提示,大型项目可能卡住几秒没反应,其实是正在解析版本并发起请求
- 如果某模块的 checksum 校验失败(比如
go.sum被手动改过),go mod download all会直接报错退出,不会跳过
离线构建前必须确认的三件事
光靠 go mod download 不能保证完全离线成功。Go 构建阶段仍可能触发额外网络请求,尤其当涉及 //go:embed、cgo、或者 build tags 分支导致部分模块未被 go list -m all 覆盖时。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 检查是否有
replace指向非本地路径(如replace example.com/a => https://github.com/x/a v1.2.0),这种写法会让go mod download忽略它——因为 Go 认为这是个远程重定向,得等真正 build 时才去抓 - 运行
go build -v -a ./...(加-a强制重编所有依赖),观察输出里有没有新出现的Fetching日志 - 确认
GOPROXY=direct且GOSUMDB=off已设好,否则即使文件都在本地,校验阶段仍可能连 sum.golang.org
为什么有时候 go mod download 没报错但 build 还是失败
最常见原因是模块版本不一致:你本地 go.mod 锁的是 v1.5.0,但 go mod download 实际拉下来的是 v1.5.1(比如因 require 行没写死版本,或用了 latest)。Go 不会自动降级,而构建时发现 hash 对不上,就拒绝使用。
- 用
go mod verify快速检查缓存中所有模块是否与go.sum一致 - 查看具体哪个模块出问题:运行
go mod download -json github.com/some/pkg@v1.5.0,对比输出里的Sum字段和go.sum是否匹配 - 遇到私有模块(如公司内网 Git)时,
go mod download默认走 GOPROXY,需提前配置git config或~/.netrc,否则静默失败
真正难搞的不是下载动作本身,而是模块版本来源混杂——go.sum 来自上次 go get,go.mod 可能手改过,缓存里又躺着别人 go mod vendor 带进来的旧版。这种情况下,go mod download 只是照单抓取,不会帮你理清关系。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










