go mod vendor 仅在 go111module=on 且存在 go.mod 时生效;go build 等命令需显式加 -mod=vendor 才启用 vendor 模式,否则仍拉公网依赖。

go mod vendor 什么时候真正生效
它只在 GO111MODULE=on 且当前目录下有 go.mod 时才起作用;go build、go test 等命令默认会忽略 vendor/,除非显式加 -mod=vendor 参数。
常见错误现象:go build 依然去拉公网模块,vendor 目录像摆设——根本没触发 vendor 模式。
- 必须用
go build -mod=vendor(或GOFLAGS=-mod=vendor全局设置) -
go run main.go不支持-mod=vendor,得先go build -mod=vendor出二进制再运行 - CI/CD 中容易漏掉这个 flag,导致离线环境构建失败
vendor 目录不是“备份”,而是“快照”
go mod vendor 复制的是当前 go.mod 解析出的**精确版本依赖树**,包括间接依赖(// indirect 标记的),但不包含 replace、exclude 或本地文件路径依赖(如 replace example.com/foo => ./foo)。
使用场景:内网构建、Air-Gapped 环境、审计包来源、锁定构建一致性。
立即学习“go语言免费学习笔记(深入)”;
- 执行前确保
go mod tidy已跑过,否则 vendor 里可能缺间接依赖 -
replace指向本地路径的模块,go mod vendor会跳过,不会复制进去——这是最常踩的坑 - vendor 后的代码仍可被
go list -m all识别为 module,但路径是vendor/xxx,不是原始 URL
离线构建失败的三个典型原因
不是 vendor 命令没跑对,而是后续链路断在了别处。
常见错误现象:go build -mod=vendor 报 cannot find module providing package xxx,明明 vendor 里有。
- 源码中 import 路径写错(比如少了个子目录),导致 go 工具找不到对应 vendor 子目录
- 某些依赖在 vendor 里但用了 cgo,而离线机器缺 C 编译器或头文件(例如
net包在 Linux 下依赖libc,但容器镜像没装glibc-devel) - Go 版本不匹配:vendor 是用 Go 1.21 生成的,但构建机是 Go 1.19,部分 stdlib 行为或 vendored 包的
go.mod版本声明不兼容
vendor 目录体积大,能删哪些
不能靠手动删,go mod vendor 本身不提供精简选项;但可以控制源头。
性能影响:vendor 过大会拖慢 git clone、CI 缓存上传、IDE 索引速度。
- 删
vendor/**/*_test.go安全,只要不跑go test -mod=vendor(测试通常不需要 vendor) - 删
vendor/**/testdata和vendor/**/examples一般不影响构建 - 不要删
vendor/modules.txt——它是 vendor 的元数据,缺失会导致-mod=vendor拒绝工作
真正省空间的办法是:用 go mod graph | grep 检查有没有意外引入的胖依赖(比如某个日志库悄悄带了整个 web 框架),从 go.mod 层面砍掉。










