ci中go mod download不命中缓存的主因是缓存路径或执行时机错误:必须同时缓存$home/go/pkg/mod(模块缓存)和~/.cache/go-build(构建缓存),且go mod download须在copy源码前执行,缓存key应基于go.sum哈希,否则无法复用。

CI里go mod download不命中缓存的常见原因
不是“没配缓存”,而是缓存路径或时机错了。Go模块缓存默认存在$GOPATH/pkg/mod,但CI runner每次都是干净环境,这个目录一启动就为空。如果go mod download在COPY . .之后执行,那它就只能重新拉包——因为go.mod还没被复制进来,go mod download压根不会运行。
- 没在Dockerfile里把
go mod download放在COPY之前,导致依赖无法提前缓存 - GitHub Actions中只缓存了
~/.cache/go-build(构建缓存),漏掉$HOME/go/pkg/mod(模块缓存) - Jenkins或GitLab CI没显式设置
GO111MODULE=on,导致go mod download静默跳过 -
go.mod文件被.dockerignore或.gitignore意外排除,CI根本看不到它
GitHub Actions中必须缓存的两个路径
只缓存一个路径,等于白干。actions/cache@v4必须同时覆盖构建缓存和模块缓存,且键要稳定。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 模块缓存路径:
$HOME/go/pkg/mod—— 存的是解压后的模块源码,go build直接读这里 - 构建缓存路径:
~/.cache/go-build—— 存的是编译中间对象,影响go build速度,但不影响go mod download - 缓存键建议用:
go-mod-${{ hashFiles('**/go.sum') }},比go.mod更稳——go.sum变意味着依赖实际变更,空格/注释不影响 - 别用
${{ runner.os }}当唯一键:Linux和macOS的$HOME路径不同,但模块内容一致,可共用缓存
Docker多阶段构建中模块缓存的关键写法
关键不是“要不要缓存”,而是“在哪一层缓存”。缓存必须发生在代码复制之前,且依赖下载命令不能带任何路径副作用。
- Dockerfile里必须这样写顺序:
COPY go.mod go.sum ./→RUN go mod download→COPY . . -
go mod download后面**不要加-x或-v**:这些参数会改变命令哈希,导致Docker层缓存失效 - 避免
RUN go get:它绕过go.mod声明,破坏可重现性;所有依赖必须由go mod download驱动 - 如果项目含
vendor/,用go mod vendor替代go mod download,但需额外校验vendor/modules.txt与go.mod一致性
缓存生效与否的快速验证方法
别猜,直接看日志。真正有效的缓存,会在输出里留下明确痕迹。
- 运行
go build -x时,如果看到cd $WORK后紧跟gccgo或compile调用,且**没有curl或fetch字样**,说明模块来自本地缓存 - 在CI日志里搜索
downloading:出现即代表缓存未命中;完全没出现,且构建时间明显缩短,大概率已生效 - 检查
go env GOCACHE和go env GOPATH输出,确认路径与缓存配置一致,尤其注意$HOME是否被CI runner重置 - 临时加一行
ls -la $HOME/go/pkg/mod/cache/download/到CI脚本,看目录下是否有大量.zip和.info文件——有,说明go mod download确实跑过了
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










