go mod download all是唯一能覆盖完整依赖树的操作,它等价于go list -m all | xargs go mod download,下载全部模块(含indirect)到$GOPATH/pkg/mod,但跳过replace到远程URL的模块,且需配合GOPROXY=direct和GOSUMDB=off才能真正直连离线构建。

直接运行 go mod download 无法绕过中间件——Go 没有“中间件”概念来拦截依赖下载;所谓“绕过”,其实是避免代理、校验、重定向等机制在下载阶段介入,让命令直连模块源并落盘。
go mod download all 是唯一能覆盖完整依赖树的操作
默认的 go mod download 只拉 go.mod 中显式 require 的模块,不碰 // indirect 条目。CI 或离线构建前若只跑这个,go build 时大概率还会触发额外 fetch。
-
go mod download all等价于go list -m all | xargs go mod download,会把整个模块图(含所有 indirect)都下到$GOPATH/pkg/mod - 它不处理
replace到本地路径的模块(本就不需下载),但会跳过replace到远程 URL 的条目(比如replace example.com/a => https://github.com/x/a v1.2.0)——这种写法会让 Go 认为“该模块由远程提供”,download阶段直接忽略,直到build时才去抓 - 执行前务必先
go mod tidy,否则go list -m all输出可能遗漏新增依赖或残留已删模块
GOPROXY=direct + GOSUMDB=off 才算真正“直连”
即使所有模块都已缓存,Go 默认仍会连接 sum.golang.org 校验 go.sum。没设 GOSUMDB=off,离线构建照样失败。
-
go env -w GOPROXY=direct:强制所有模块走原始源(如 GitHub、GitLab),不经过任何代理 -
go env -w GOSUMDB=off:关闭校验服务器,仅比对本地go.sum文件 - 两者必须同时生效;只设
direct不关sumdb,构建时仍会报failed to fetch checksums - 私有域名(如
git.company.com)在GOPROXY=direct下自动直连,无需额外配置
注意 replace 和 exclude 的实际影响
go mod download all 对 replace 和 exclude 的处理不一致,容易误判是否真“下全了”。
-
replace指向远程 URL(如https://...)的模块:不会被download,也不会出现在go list -m all输出里——它被当成“外部引用”,只有构建时才解析 -
exclude的模块:只要还在go list -m all结果中(比如被其他未 exclude 模块间接依赖),download all依然会拉它 - 验证是否真被跳过:运行
go list -m all | grep 'your-module-name',再看go mod download是否报错或静默跳过
最常被忽略的是:即使 go mod download all 成功,go build -a 仍可能触发新请求——比如用了 //go:embed 引用未声明的文件,或 cgo 导致某些平台特定模块在 build 阶段才被识别。别只信 download 输出,得用 go build -v -a . 实际跑一遍看有没有 Fetching 日志。

















