直接结论:用go mod vendor + go build -mod=vendor,但必须确保go111module=on且项目有go.mod;否则vendor目录生成失败或不生效。它只复制go.mod中require的直接和间接依赖(实际构建用到的模块级内容),不包含本地replace路径和仅测试用包;构建时必须显式启用-mod=vendor(或设goflags="-mod=vendor"),并配合goproxy=off、gosumdb=off及完整go.sum方可离线可靠运行。

直接结论:用 go mod vendor + go build -mod=vendor,但必须确保 GO111MODULE=on 且项目有 go.mod;否则 vendor 目录生成失败或不生效。
为什么 go mod vendor 没反应?
常见现象是执行后 vendor/ 为空、不存在,或只生成了空目录。根本原因不是命令错,而是 Go 没进模块模式:
-
GO111MODULE环境变量不是on(尤其在GOPATH项目里,默认可能是auto或off) - 项目根目录下没有
go.mod文件(go mod init没运行过) - 当前工作目录不是模块根目录(比如在子目录里执行,但
go.mod在上级)
验证方式:go env GO111MODULE 应输出 on;go list -m 应输出模块路径(如 example.com/myproject),而非 command-line-arguments。
go mod vendor 实际复制哪些依赖?
它只复制 go.mod 中 require 声明的直接和间接依赖(即整个构建图中实际用到的模块),但有明确限制:
- 不处理
replace指向本地路径(如replace example.com/a => ./local/a),这种路径不会被复制进vendor/,构建时仍需该本地路径存在 - 不包含仅用于测试的依赖(
_test.go中 import 但主代码未引用的包),除非它们也被主代码间接引用 - 复制的是“模块级”内容:即使代码只用了
golang.org/x/net/http2,整个x/net模块都会进vendor/
生成的 vendor/modules.txt 是关键依据,记录每个模块来源和版本,CI 构建前应校验其完整性。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
构建时如何真正强制走 vendor/?
光有 vendor/ 目录完全不够。Go 默认仍会读取 $GOPATH/pkg/mod 缓存或代理,必须显式启用 vendor 模式:
- 每次构建加参数:
go build -mod=vendor(Go 1.14+ 支持,要求vendor/modules.txt存在) - 或设环境变量:
GOFLAGS="-mod=vendor"(推荐,全局生效,避免 CI 脚本漏写)
注意:-mod=vendor 会跳过 go.mod 中所有 replace(包括本地路径),这点极易踩坑——若你依赖本地 fork,构建会直接失败。
验证是否生效:加 -x 参数编译,看日志中 compile 是否从 vendor/golang.org/x/net/http2 这类路径读取文件。
离线构建前最容易忽略的三件事
vendor 模式常用于离线环境,但以下三点不处理,构建大概率失败:
-
go.sum必须完整:离线时go build -mod=vendor仍会校验 checksum,缺失条目会报checksum mismatch;在线时先跑go mod verify,确认无误再打包 - 关掉校验服务:
GOPROXY=off GOSUMDB=off,否则构建过程可能卡住或报错 -
vendor/和根目录的go.mod、go.sum必须一起提交——vendor/里的go.mod和go.sum是生成快照,不参与构建解析,真正起作用的是根目录那两个文件
复杂点在于:vendor 不是“开关一开就自动锁死”,它依赖模块模式的前置状态、构建参数的显式声明、以及离线环境下校验机制的同步关闭。少一个环节,就等于没锁。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










