Go模块依赖下载慢的根本原因是本地缓存未被正确复用,需确保$GOPATH/pkg/mod路径稳定、GOPROXY配置可靠(如https://goproxy.cn,direct)、避免执行go clean -modcache,并在CI/CD中持久化该目录及~/.cache/go-build。

日常开发中 Go 模块依赖下载慢,根本不是网络问题,而是缓存没被正确复用。 你每次 go build 或 go test 前的“finding”“downloading”日志,基本都来自 go mod download 阶段未命中本地模块缓存,而非构建缓存(GOCACHE)失效——这两者完全独立,别混了。
go mod download 为什么总在重拉?
它只看 $GOPATH/pkg/mod 目录是否存在对应模块的解压后文件。只要这个目录被清空、路径变动、或 GO111MODULE 状态不一致,就退回到网络拉取。
-
go clean -modcache是最常见的人为清空操作,CI 脚本里若存在这行,等于主动放弃所有模块缓存 -
GO111MODULE=off时,go mod download不生效,会 fallback 到 GOPATH mode,不走模块缓存路径 - 切换
GOPATH(比如临时改了环境变量),$GOPATH/pkg/mod就变成另一个空目录,旧缓存不可见 - 没设
GOPROXY或代理不稳定,首次下载失败后可能残留不完整目录,导致后续go mod download认为“缺失”,反复尝试拉取
怎么让 go mod download 稳定复用本地缓存?
核心是确保 $GOPATH/pkg/mod 目录长期存在、可写、且被所有命令一致访问。
- 运行
go env GOPATH确认当前GOPATH路径,别用~/go这种相对路径写进脚本;固定为绝对路径,如/home/user/go - 执行
go mod download后,检查$GOPATH/pkg/mod/cache/download/下是否有.zip文件、$GOPATH/pkg/mod/下是否有对应模块的符号链接和源码目录——有才算真正缓存成功 - 开发机上建议直接
go env -w GOPROXY=https://goproxy.cn,direct,避免因代理超时触发降级直连,造成部分模块漏缓存 - VS Code 的 Go 插件默认启用
gopls,它也会触发go mod download;若发现编辑器频繁卡在 “Loading packages”,先检查gopls日志里是否在重复下载,再确认GOPATH是否与终端一致
Docker 构建时模块缓存总失效?
不是 Dockerfile 写得不对,而是缓存层没对准关键路径。Docker 只能按指令顺序缓存,COPY . . 之后的所有层都失效,但模块缓存必须在代码复制前就落盘。
-
go mod download必须放在COPY之前,且前面不能有改变工作目录或ENV GOPATH的指令(否则缓存键变化) - 多阶段构建中,build 阶段的
$GOPATH/pkg/mod不会自动传给 final 阶段;final 阶段不需要它,但 build 阶段必须保留该目录用于复用 - GitHub Actions 中用
actions/cache@v4时,缓存 key 必须包含go-${{ hashFiles('**/go.sum') }},否则go.sum改了但缓存没刷新,会导致版本错乱 - 本地开发用 Docker Compose 构建时,别只挂载
.:/app;应额外挂载~/.cache/go-build:/root/.cache/go-build和$HOME/go/pkg/mod:/root/go/pkg/mod,否则容器内go mod download永远从零开始
缓存不是开了就自动变快,它依赖路径稳定、代理可靠、命令一致三个条件同时满足。最容易被忽略的是:你本地 go env GOPATH 和 CI 中的 GOPATH 是否真的一样,以及 go.mod 文件里有没有意外引入了 require 未声明的间接依赖——这种情况下,go mod download 会试图补全,而补全过程不走已有缓存。

















