go mod download 默认拉取所有 go.mod 中 require 的模块(含间接依赖),不区分是否实际使用;它仅依据 go.mod 静态声明下载,不解析构建标签、平台条件或代码导入图,因此未启用的 // +build 分支或 cgo 相关模块也会被一并下载。

为什么 go mod download 会拉取所有依赖,包括不用的模块?
Go 的模块机制默认以 go.mod 文件为准,只要出现在 require 列表里(哪怕只被某个未启用的 // +build 分支引用),go mod download 就会一并下载。尤其在大型项目中,某些模块可能仅用于特定平台(如 linux/amd64)或调试工具(如 github.com/go-delve/delve),但 go build 或 go test 并不实际加载它们。
用 -mod=readonly 和 -tags 控制实际加载路径
真正影响依赖解析的是构建时的导入图,而非 go.mod 的静态列表。关键在于让 Go 工具链“看不见”那些不参与当前构建的代码:
-
go build -mod=readonly -tags=!debug:跳过带// +build debug标签的文件,其 import 语句不会被扫描,对应模块就不会触发下载 -
go build -mod=readonly -tags=netgo:避免引入cgo相关模块(如golang.org/x/sys的部分子包),前提是代码里没硬编码依赖 - 确保
GO111MODULE=on,否则-mod=readonly不生效
replace 和 exclude 不解决下载问题,慎用
replace 只改路径,不删依赖;exclude 仅阻止构建时使用,但 go mod download 仍会拉取——它不检查是否排除,只看 go.mod 是否声明。
- 想跳过下载,必须从源头移除该模块的 import,或用构建标签屏蔽含 import 的文件
-
go mod edit -droprequire=github.com/unused/pkg是唯一能彻底删掉下载项的操作,但需确认无任何代码路径会间接依赖它 - CI 中可加
go list -deps -f '{{if (not .Standard)}}{{.ImportPath}}{{end}}' ./... | sort -u验证实际用到的非标准库模块
本地开发时用 go mod vendor 配合 .gitignore 精简
如果只是想避免反复下载,而不是跳过某几个模块,vendor 是更稳的选择:
-
go mod vendor后,go build -mod=vendor完全不联网,也不读go.mod里的require - 把
vendor/提交进 Git,但注意:若模块含cgo或平台相关代码,跨平台 vendor 可能失效 - 可在
.gitignore里留一行!/vendor/modules.txt,保证依赖快照可追溯,又不提交全部源码
真正难处理的是间接依赖里混着高延迟模块(比如某些国内无法直连的私有 registry),这种时候得靠 GOPROXY 配置或镜像,不是靠跳过能解决的。

















