go mod vendor 生成 vendor 目录需显式执行,依赖 go.mod 存在且版本与 vendor/modules.txt 严格一致;-mod=vendor 不保证完全离线,replace 本地路径被忽略,vendor 体积大且难审计,多数场景推荐 GOPROXY 替代。

vendor 目录不是必须手动创建的
Go 1.6+ 默认启用 GO111MODULE=on 后,go mod vendor 才会生成 vendor/ 目录;如果项目根目录下有 go.mod,但没运行过该命令,vendor/ 就不存在——它不会自动出现,也不会被构建流程隐式使用。
常见错误是以为只要建了 vendor/ 文件夹、把包拷进去就能离线构建,其实不行:Go 工具链只认 go mod vendor 生成的结构,包括 vendor/modules.txt 校验文件。否则 go build -mod=vendor 会报错:loading module graph: no go.mod file in current directory 或跳过 vendor 直接走 proxy。
-
go mod vendor必须在有go.mod的目录下执行 - 执行后会拉取所有依赖(含间接依赖)到
vendor/,并写入vendor/modules.txt - 后续构建需显式加
-mod=vendor参数,例如:go build -mod=vendor ./cmd/app - 若想让所有子命令默认走 vendor,可设环境变量:
GOFLAGS="-mod=vendor"
go build -mod=vendor 不等于“完全离线”
即使用了 -mod=vendor,Go 仍可能发起网络请求——比如你本地 go.mod 里写了 require example.com/foo v1.2.3,但 vendor/modules.txt 里记录的是 v1.2.4,这时 Go 会尝试去 fetch v1.2.3 的 go.sum 条目,导致失败或超时。
根本原因是:go.mod 和 vendor/modules.txt 版本不一致。解决方式不是删掉 go.sum,而是同步二者:
立即学习“go语言免费学习笔记(深入)”;
- 先运行
go mod tidy确保go.mod和go.sum一致 - 再运行
go mod vendor,它会按go.mod中声明的版本拉取,并更新vendor/modules.txt - 检查
vendor/modules.txt第一行是否与go.mod中require的版本完全匹配 - CI 中建议加校验步骤:
diff -u
vendor 下的 replace 语句会被忽略
如果你在 go.mod 里写了 replace github.com/some/pkg => ./local-pkg,那么 go mod vendor 默认不会把 ./local-pkg 拷进 vendor/,也不会在 vendor/modules.txt 中体现替换关系——它只处理远程模块。
这意味着:用 -mod=vendor 构建时,replace 失效,Go 会尝试从原始路径加载,结果往往报错 cannot find module providing package。
- 临时方案:改用
replace github.com/some/pkg => /abs/path/to/local-pkg(绝对路径),并确保该路径在构建机上存在 - 长期方案:把本地修改推送到私有仓库,用
replace+go mod edit -replace切换,再go mod vendor - 注意:
go mod vendor不支持--no-verify或类似开关,无法跳过校验强制包含本地路径
vendor 目录体积大且难以审计
一个中等规模项目执行 go mod vendor 后,vendor/ 往往超过 50MB,包含大量测试文件、文档、未使用子模块——这不仅拖慢 CI 下载,也让安全扫描(如 govulncheck)变慢甚至超时。
Go 官方不提供精简 vendor 的内置机制,但可通过以下方式控制:
- 用
go mod vendor -v查看哪些模块被拉入,结合go list -deps -f '{{.Path}}' ./... | grep -v 'test'排查冗余依赖 - 删除 vendor 中无用内容(如
**/*_test.go、**/testdata/**),但要保留vendor/modules.txt和vendor/cache/(如有) - CI 中建议用
rsync -av --exclude='*_test.go' --exclude='testdata' vendor/ vendor-clean/做轻量裁剪 - 更彻底的做法是放弃 vendor,改用
go mod download+GOPROXY=file://...搭建本地模块缓存,兼顾可控性与体积
真正需要 vendor 的场景其实很窄:内网无代理、构建机不允许联网、或审计要求源码全量归档。多数情况下,go.mod + go.sum + 可信 proxy 已足够可靠。









