go mod vendor 只复制被 import 引入且参与编译的模块(含 indirect 依赖),不复制测试专用依赖或 replace 本地路径模块(除非加 -v);vendor 目录含自动生成的只读 go.mod 快照,-mod=vendor 失效常见于 go111module=off 或工作区错位。

go mod vendor 会复制哪些模块
它只复制 go.mod 中直接或间接声明、且当前构建中实际用到的模块(即被 import 引入并参与编译的包),不会复制测试专用依赖(如 _test 中用到但主代码没用的模块),也不会复制 replace 指向本地路径的模块——除非你加了 -v 参数且该路径在 vendor 范围内。
常见错误现象:go mod vendor 后 go build 失败,报错找不到某个包,往往是因为该包仅出现在 go test 中,或被 //go:embed 或 //go:generate 间接引用但未被 import;这时得手动确保它被主模块显式 import,或改用 go mod vendor -v 强制包含。
- 使用场景:CI 环境无外网、离线构建、审计依赖快照
-
go mod vendor默认不拉取indirect依赖,除非它们被实际 import;可加-v查看详细日志确认哪些模块被跳过 - 性能影响:大型项目 vendor 后目录可能达百 MB,
git status变慢,建议在.gitignore中排除/vendor——但若需提交 vendor,则必须确保go.mod和go.sum与 vendor 内容严格一致
vendor 目录下为什么还有 go.mod 文件
这是 Go 1.14+ 的行为:vendor 目录里会生成一个精简版 go.mod,只保留 module 声明和 require 列表(不含 replace / exclude),用于让 Go 工具链识别 vendor 是“自洽的依赖副本”。它不是用来编辑的,也不参与主模块解析。
容易踩的坑:有人误删 vendor 下的 go.mod,导致 go build -mod=vendor 报错 no required module provides package;也有人试图修改它来“修复依赖”,结果破坏 vendor 一致性,后续 go mod tidy 会把它覆盖掉。
立即学习“go语言免费学习笔记(深入)”;
- 这个
go.mod是只读快照,每次go mod vendor都会重写 - 如果项目用了
replace,vendor 中对应模块的内容仍是替换后的版本,但go.mod里仍显示原始路径和版本号 - 兼容性注意:Go 1.13 及更早版本不生成此文件,且
-mod=vendor行为略有差异;线上构建环境务必统一 Go 版本
go build -mod=vendor 不生效的典型原因
最常见的是环境变量或 go 命令参数冲突:GO111MODULE=on 是前提,否则 -mod=vendor 被忽略;其次,如果当前目录外有 go.mod(比如在子目录运行命令),Go 可能定位到父级模块,导致 vendor 路径错位。
错误现象示例:go build -mod=vendor 仍去拉公网模块,终端打印 Fetching ...;或者报错 cannot find module providing package xxx,但 vendor 里明明有那个包。
- 确认方式:运行
go env GO111MODULE,必须是on;临时启用可用GO111MODULE=on go build -mod=vendor - 确保在
go.mod所在根目录执行命令,避免工作区污染 - 检查是否有
go.work文件存在——多模块工作区下-mod=vendor默认不生效,需显式用go work use .切回单模块上下文 - Windows 用户注意:路径分隔符不影响,但
vendor必须是小写目录名,Vendor或VENDOR会导致失败
vendor 后如何安全更新某个依赖
不能直接改 vendor 里的代码,也不能只改 go.mod 然后跑 go mod vendor ——这会把整个 vendor 目录刷掉,可能引入意外变更。正确做法是先升级依赖声明,再重新 vendor,并验证。
关键点在于:vendor 是 go.mod 的衍生品,不是源;所有变更必须从 go.mod 出发。
- 更新单个依赖:运行
go get example.com/pkg@v1.2.3,再执行go mod tidy,最后go mod vendor - 降级依赖:同样用
go get指定旧版本,go mod tidy会自动清理冗余项 - 如果只想更新 vendor 内容而不改
go.mod(比如修复 vendor 中某文件权限),应先rm -rf vendor,再go mod vendor,而不是手工增删 - 注意
go.sum:vendor 后go.sum不会自动更新,但下次go build或go mod tidy会校验 vendor 内容是否匹配 sum 记录;不匹配会报错,此时需人工核对或重跑go mod vendor
go.mod 快照,任何绕过声明的修改都会在下次 vendor 或构建时暴露出来。真正麻烦的从来不是命令本身,而是模块路径别名、replace 嵌套、以及跨 Go 版本的 vendor 行为漂移。










