go build 默认忽略vendor目录,必须显式加-mod=vendor参数才能启用;否则仍走模块缓存或网络,导致本地与CI行为不一致。

go build 时 vendor 目录被忽略或误用
Go 工具链在 module 模式下默认优先使用 go.mod 和模块缓存,vendor/ 目录只有显式启用才会生效。如果你运行 go build 却没加 -mod=vendor,它根本不会看 vendor/ 里的代码,而是从 $GOPATH/pkg/mod 或网络拉取——这正是行为不一致的根源。
常见现象包括:本地能编译,CI 失败;或 go mod vendor 后仍报 cannot find package。
- 必须用
go build -mod=vendor(或go test -mod=vendor)才能强制走vendor/ -
GOFLAGS="-mod=vendor"可全局设置,但 CI 中建议显式写入命令,避免环境变量遗漏 - 若项目同时存在
go.mod和vendor/,但未指定-mod=vendor,Go 会忽略vendor/并按模块规则解析依赖——此时 vendor 成了“摆设”
go mod vendor 执行后仍提示 Inconsistent vendoring detected
这个错误不是警告,是硬性拒绝:Go 发现 vendor/ 内容与 go.mod + go.sum 不匹配,比如文件缺失、校验和错、或有手动修改痕迹。
直接删掉 vendor/ 再重来往往比修修补补更可靠。
- 执行
rm -rf vendor彻底清空旧目录 - 运行
go clean -modcache清理本地模块缓存(尤其当你刚切换过镜像或代理) - 再跑
go mod vendor—— 它会重新下载所有依赖并严格按go.sum校验 - 最后用
go mod verify确认:输出all modules verified才算真正一致
Glide 遗留项目中嵌套 vendor 导致重复包
老项目用 Glide 管理依赖时,第三方库自带 vendor/ 是常态。如果不清理,go mod vendor 会把嵌套的 vendor/ 也复制进来,导致同一包出现多个路径(如 vendor/a/b 和 vendor/c/d/vendor/a/b),Go 构建时可能选错版本。
Glide 的 --strip-vendor(简写 -v)是专治这个的,但只对 Glide 生效;迁移到 Go Modules 后,得靠人工干预或脚本清理。
- 迁移前:用
glide install -s -v生成扁平化vendor/,再基于此初始化go mod init - 迁移后:检查
vendor/下是否还有子目录含vendor/,如有,手动删掉(find vendor -name vendor -type d -delete) - 后续维护:禁止向
go.mod中replace到带vendor/的 fork 路径,否则go mod vendor可能再次引入嵌套
私有仓库或 replace 导致 vendor 内容缺失
当 go.mod 里用了 replace 指向本地路径,或 exclude 排除某个版本,go mod vendor 默认不会把 replace 目标或被 exclude 的模块放进 vendor/——但它也不会报错,只是静默跳过,结果就是 vendor 缺包。
这种缺失很难一眼发现,直到构建失败才暴露。
- 运行
go list -m all | grep '=>'查看哪些模块被replace或exclude了 - 对
replace到本地路径的模块,确保该路径存在且可读;必要时用go mod edit -replace临时切回远程地址再go mod vendor - 对
exclude的模块,确认它确实不该进 vendor;否则删掉exclude行,再go mod tidy && go mod vendor
vendor 目录本身不解决冲突,它只固化当前依赖快照。真正要稳,得让 go.mod 和 go.sum 保持干净、可复现,再用 -mod=vendor 显式启用——否则它随时可能被工具链绕过。

















