go mod vendor 不会自动创建 vendor 目录,必须显式执行且依赖有效的 go.mod;它按 go.mod 和 go.sum 复制所有依赖到 vendor/ 并生成 modules.txt,构建时需显式加 -mod=vendor 参数才真正使用 vendor 内容。

go mod vendor 生成 vendor 目录必须显式执行
vendor 目录不会自动创建,也不会随 go.mod 出现而自动生成。你得手动运行 go mod vendor,且前提是当前目录下已存在有效的 go.mod 文件。常见错误是直接在老项目里执行该命令,结果报 go: no modules found —— 先补上 go mod init example.com/myproject 再试。
go mod vendor 做的事很明确:按 go.mod 和 go.sum 中声明的版本,把所有直接和间接依赖(transitive dependencies)完整复制进 vendor/,同时生成 vendor/modules.txt 记录每个模块的确切来源与版本。这个文件是校验依据,不能手动修改或删掉。
- 加
-v参数可看到复制过程,方便排查缺失包(比如私有仓库未配置 SSH 或 token) - 它不处理
replace指向本地路径的模块(如replace github.com/foo => ../foo),这类包不会进vendor/ - 测试专用依赖(仅在
*_test.go中 import 的包)默认不复制,除非也被主代码引用
go build -mod=vendor 是强制走 vendor 的唯一可靠方式
即使 vendor/ 目录存在,go build 默认仍会读取 $GOPATH/pkg/mod 缓存,而不是 vendor/。漏掉 -mod=vendor,就等于白放 vendor —— 构建可能成功,但加载的是缓存里的版本,和 vendor 内容不一致。
CI/CD 脚本里最容易踩这个坑。例如:go test ./... 不加参数,实际跑的是模块缓存;正确写法是 go test -mod=vendor ./...。若想全局生效,可设环境变量 GOFLAGS="-mod=vendor",但要注意它会影响所有子命令(包括 go list、go mod tidy 等)。
立即学习“go语言免费学习笔记(深入)”;
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
-
go run -mod=vendor main.go同样需要显式加参数 -
-mod=vendor不等于“完全离线”:如果go.mod和vendor/modules.txt版本不一致,Go 仍会尝试联网 fetch 缺失的go.sum条目 - 验证是否真走 vendor?临时清空
$GOPATH/pkg/mod/cache或设GOPROXY=off,再不加参数运行go build,应直接报错
vendor 与 go.sum 必须同步,否则校验失败
go build -mod=vendor 仍会读 go.sum 校验 vendor 里的代码哈希是否匹配。删掉 go.sum 或让它过期,会直接报 verifying github.com/xxx@v1.2.3: checksum mismatch。
go mod vendor 不会自动更新 go.sum —— 它只复制代码。所以更新依赖后,必须先运行 go mod tidy(补全/清理 go.mod 和 go.sum),再跑 go mod vendor。否则 go.sum 里缺条目,或版本对不上 vendor/modules.txt,离线构建就会崩。
- CI 中建议加一步校验:
diff -u -
go mod verify可检查 vendor 是否被篡改,但它不修复go.sum;真正补全需go build -mod=readonly触发 - 私有仓库依赖用
git+ssh协议时,vendor 后可能丢失 .git 信息,导致go list -m all显示版本为devel,影响可重现性
IDE 和工具链默认不识别 vendor 模式
VS Code + gopls、gofmt、go vet 等工具默认按模块模式运行,不自动加 -mod=vendor。你会看到编辑器提示 “no packages found” 或 “cannot find package”,但 go build -mod=vendor 实际能成功编译 —— 这不是 bug,是预期行为。
要让 IDE 正常工作,必须手动配置。例如 VS Code 的 settings.json 加:"go.toolsEnvVars": {"GOFLAGS": "-mod=vendor"}。注意:这会让所有 Go 工具命令都带上该 flag,包括 go mod 类命令,可能干扰日常开发(如 go mod edit 会报错)。
-
replace指令在 vendor 模式下仍有效,但go mod vendor不处理本地路径替换 —— 替换逻辑由模块系统在解析阶段完成,vendor 只是源码快照 - vendor 目录里不能有
go.mod文件,否则go build -mod=vendor会报go: inconsistent vendoring - 提交 vendor 到 Git 是双刃剑:保证环境一致,但体积大、diff 难读;若选择不提交,CI 必须确保每次
go mod vendor结果确定(依赖源稳定、无 force push)
-mod=vendor 是开关,不是魔法;go.sum 和 vendor/modules.txt 必须三者严格对齐,缺一不可。

















