go mod vendor 生成的包不能直接归档,因为它只复制 go.mod 中 require 声明的模块,不包含 replace、exclude 或未被 import 的间接依赖;本地 replace 路径(如 ./localpkg)默认不进 vendor,归档后编译会失败;必须确保 go.mod 和 go.sum 已提交、无临时 replace,并搭配 vendor 目录一起归档才具备可重现构建能力。

go mod vendor 生成的包为什么不能直接归档?
因为 go mod vendor 只复制 require 列表里显式声明的模块,不包含 replace、exclude 或间接依赖中被覆盖/替换的路径。如果你用 replace ./localpkg 指向本地开发目录,vendor/ 里根本不会出现它——归档后编译直接失败。
归档前必须确认 go.mod 的 clean 状态
运行 go mod tidy 后,检查 go.mod 是否还有未提交的修改或临时 replace。常见陷阱是:本地调试时加了 replace github.com/foo/bar => ../bar,但忘了删掉再 commit —— 这会导致别人拉代码后 go build 找不到 ../bar。
- 执行
git status go.mod go.sum,确保二者已提交且无 diff - 临时
replace必须移除,或改用go mod edit -dropreplace=... - 如果依赖私有仓库,确认
GOINSECURE或git config配置已同步到归档说明里
真正可归档的源码包 = vendor + go.mod + go.sum + .gitignore(精简版)
只打包 vendor/ 目录不够,缺少 go.mod 和 go.sum 就无法验证依赖一致性;而保留完整 .git/ 会极大增加体积,且违反“源码归档”本意。正确做法是:
- 运行
go mod vendor(Go 1.14+ 默认启用) - 删除
.git/、node_modules/、build/等非 Go 构建必需目录 - 保留最小必要文件:
go.mod、go.sum、vendor/、main.go(或 cmd/)及业务代码 - 用
tar -czf myapp-v1.2.0-src.tgz --exclude='*.log' --exclude='.DS_Store' ./打包
CI 中一键归档脚本的关键检查点
自动化归档容易忽略环境差异。比如 CI 使用 Go 1.21,但你本地用 Go 1.19 —— go.sum 格式可能不兼容。实际脚本里必须锁定 Go 版本并校验哈希:
- 开头加
go version | grep 'go1\.2[0-9]'断言版本 -
go mod verify必须成功,否则中断归档 - 打包后执行
tar -tzf myapp-src.tgz | grep -q 'vendor/github.com/'确认 vendor 非空 - 避免用
go build -o /dev/null .测试,它不检查 vendor 完整性;应改用go list -m all | wc -l对比 vendor 下模块数
归档不是压缩完就结束,关键在「脱离原始开发环境后能否干净构建」——所有路径、替换、校验都得在打包那一刻固化下来,少一个 go.sum 行,上线时就可能多一个深夜告警。











