根本原因是项目未初始化模块或GO111MODULE未生效;必须确保go.mod存在且go env GO111MODULE输出on,同时配置GOPROXY=https://goproxy.cn,direct以解决国内依赖拉取失败问题。

go build 或 go run 为什么没自动下载依赖?
根本原因通常只有两个:项目没初始化为模块,或 GO111MODULE 实际未生效。Go 1.16+ 虽默认开启模块模式,但前提是当前目录下存在 go.mod —— 如果只是 git clone 下来一个空项目,go build 会退回到 GOPATH 模式,完全不查 go.mod,更不会下载任何第三方包。
验证方式很简单:go env GO111MODULE 输出必须是 on;ls go.mod 必须存在。两者缺一不可。
- 若
go.mod缺失:运行go mod init example.com/myapp(模块名可任意,但别用main或标准库名) - 若
GO111MODULE=off:执行go env -w GO111MODULE=on - 注意:某些 IDE(如旧版 Goland)可能在终端里覆盖环境变量,建议在纯 shell 中测试
国内环境下 GOPROXY 必须设对,否则卡死在 downloading…
默认代理 https://proxy.golang.org 在国内基本不可用,go build 会超时失败,错误常表现为:Get "https://proxy.golang.org/...": dial tcp: i/o timeout。这不是网络问题,是代理不可达。
正确做法是显式设置国内镜像:
- 推荐命令:
go env -w GOPROXY=https://goproxy.cn,direct -
direct是关键:当某个模块在代理中找不到(比如私有仓库),会 fallback 到直连,避免整个构建中断 - 验证是否生效:
go env GOPROXY应输出完整地址,不是https://proxy.golang.org或空值 - 临时覆盖(CI 场景):
GOPROXY=https://goproxy.cn,direct go build -v
go mod tidy 和 go mod download 的分工要分清
go mod tidy 不是“下载命令”,它是“依赖同步器”:扫描代码里的 import,补全 go.mod 中缺失的 require 行,并删掉未使用的依赖。它触发下载,但本质是修正声明。
go mod download 才是纯下载命令:只读 go.mod,把里面所有 require 列出的模块拉到本地缓存($GOPATH/pkg/mod),不改任何文件。
- 首次拉取项目后,先跑
go mod tidy确保go.mod完整,再跑go mod download预加载——这样 CI 构建时go build就真正“零等待” - 想只下某一个包:
go mod download github.com/gin-gonic/gin@v1.9.1 - 想验证缓存完整性:
go mod verify,失败说明某模块校验和不匹配(常见于手动改过go.sum)
vendor 目录不是必需的,但离线构建必须它
绝大多数场景下,你不需要 vendor。Go 默认从 $GOPATH/pkg/mod 读依赖,速度快、空间共享。只有两种情况才需要 go mod vendor:
- 构建环境完全无法联网(如内网服务器),且不允许配置
GOPROXY - 团队强制要求所有依赖代码随项目提交,规避模块代理失效风险
注意:go mod vendor 会复制全部依赖(含间接依赖)到项目根目录下的 vendor/,体积暴涨;后续 go build -mod=vendor 才会优先用它。漏掉 -mod=vendor 参数,还是走模块缓存。
真正影响速度的从来不是 vendor 存不存在,而是 go.mod 是否干净、GOPROXY 是否可用、以及有没有人在 go.sum 里手动画蛇添足。

















