Go 1.14+ 默认不自动使用 vendor 目录,需显式指定 -mod=vendor;go mod vendor 可能遗漏隐式依赖,应清理后配合 go mod tidy 重生成;离线构建必须设置 GOPROXY=off、GOSUMDB=off,并确保根目录 go.mod 和 go.sum 完整。

Go vendor 目录为什么没被自动使用
Go 1.14+ 默认关闭 GO111MODULE=on 时的 vendor 优先行为,即使项目里有 vendor/ 目录,go build 仍会去拉取远程模块——这不是 bug,是设计变更。
必须显式启用 vendor 模式:
- 临时生效:
GO111MODULE=on go build -mod=vendor - 永久生效(推荐):在项目根目录加
go.mod后,执行go mod vendor,再始终带上-mod=vendor参数 - 注意:
go run和go test同样需要-mod=vendor,否则跳过 vendor
go mod vendor 生成的 vendor/ 不完整怎么办
常见现象是构建时报错找不到某个包,比如 cannot find module providing package github.com/sirupsen/logrus,但 vendor/github.com/sirupsen/logrus 明明存在——本质是 go mod vendor 只拷贝 go list -deps 能识别到的依赖,漏掉隐式 import 或 build tag 分支里的包。
解决办法:
立即学习“go语言免费学习笔记(深入)”;
- 先清理再重做:
rm -rf vendor/ && go mod tidy && go mod vendor - 确保所有平台相关代码都被扫描:用
GOOS=linux GOARCH=amd64 go mod vendor(按目标离线环境设) - 检查是否有
// +build标签控制的文件未被当前构建环境加载,可临时删掉 build tag 测试
离线构建时 GOPROXY 和 GOSUMDB 必须关掉
即使用了 vendor,Go 工具链在某些阶段(如 go list、go mod download)仍会尝试连接 proxy.golang.org 或校验 checksum,导致离线失败。
正确做法是彻底隔离网络依赖:
- 设置:
GOPROXY=off GOSUMDB=off - 验证是否生效:
go env GOPROXY GOSUMDB应输出off - 如果用 CI 或容器,建议在构建脚本开头就 export 这两个变量,避免被子进程继承默认值
vendor/ 下的 go.mod 和 go.sum 是摆设吗
不是摆设,但作用有限。vendor 目录里的 go.mod 和 go.sum 是生成时快照,仅用于 go mod vendor 自身校验,不参与构建时依赖解析。
真正影响构建的是项目根目录的 go.mod 和 go.sum。离线环境下容易忽略这点:
- 若根目录
go.sum缺失或不全,go build -mod=vendor仍可能报 checksum mismatch - 解决方案:在线环境先跑一遍
go mod verify确保go.sum完整,再把整个项目(含go.mod、go.sum、vendor/)打包带走 - 别只同步
vendor/,那是最常踩的坑
离线构建真正的复杂点不在 vendor 本身,而在于 Go 工具链多个环节对网络的隐式依赖——从模块解析、校验到构建缓存,都可能悄悄往外发请求。关掉 GOPROXY 和 GOSUMDB、坚持用 -mod=vendor、带全根目录元信息,三者缺一不可。










