gomodcache是唯一控制go模块下载缓存目录的环境变量,goenv和gopath无法改变该路径;它默认为$gopath/pkg/mod,可设为任意可写绝对路径,需用go env gomodcache验证生效。

GOENV 和 GOPATH 不能控制模块下载缓存目录
很多人以为设置 GOPATH 或 GOENV 就能改变 Go 模块下载时的临时存放位置,其实不是。Go 1.11+ 的模块模式下,依赖下载默认缓存在 $GOPATH/pkg/mod,但这个路径不受 GOPATH 环境变量“动态覆盖”——它只在首次初始化时读取,且模块缓存是全局共享的,和当前项目 GOPATH 无关。
真正起作用的是 GOPROXY、GOSUMDB 这类代理配置,而缓存目录由另一个独立变量控制:
-
GOCACHE:控制构建缓存(go build产生的中间文件),不是模块下载目录 -
GOMODCACHE:这才是你要找的——Go 官方自 1.13 起支持的环境变量,用于显式指定模块下载缓存根目录
设置 GOMODCACHE 才能真正重定向模块下载位置
GOMODCACHE 是唯一被 go 命令直接识别并用于定位 pkg/mod 子目录的环境变量。它必须指向一个可写、干净的绝对路径,Go 会在其下自动创建 cache、download、sumdb 等子结构。
实操建议:
- Linux/macOS:在 shell 配置中添加
export GOMODCACHE="/path/to/your/modcache",然后source生效 - Windows(CMD):运行
set GOMODCACHE=C:\go\modcache;PowerShell 用$env:GOMODCACHE="C:\go\modcache" - 验证是否生效:执行
go env GOMODCACHE,输出应为你设置的路径 - 注意:修改后需重启终端或重新加载 shell,已有进程不会自动继承新值
为什么有时改了 GOMODCACHE 还看到旧缓存被读取?
这不是配置失效,而是 Go 的模块查找逻辑导致的“假象”。go 命令会按顺序检查多个位置:
- 先查
GOMODCACHE指向的路径 - 若未命中,再 fallback 到默认路径
$GOPATH/pkg/mod - 如果旧缓存里已有你需要的版本,它就直接用了,不会报错也不会提醒你“正在用默认路径”
所以常见错误现象:go list -m all 正常执行,但 du -sh $GOPATH/pkg/mod 仍很大——说明旧缓存还在被读,但新下载会进 GOMODCACHE。
彻底清理旧缓存的方法:
- 手动删除
$GOPATH/pkg/mod目录(确保没有其他项目正依赖它) - 或者用
go clean -modcache,该命令会清空当前GOMODCACHE指向的位置,**不会动$GOPATH/pkg/mod** ——所以务必先确认go env GOMODCACHE输出正确
CI/CD 中使用 GOMODCACHE 的注意事项
在 GitHub Actions、GitLab CI 等环境中,GOMODCACHE 很有用,但容易踩两个坑:
- 路径权限问题:比如设为
/tmp/go-modcache,某些 runner 默认不允许写入/tmp下的子目录,或会在 job 结束时清空,导致缓存失效 - 路径未持久化:即使设置了
GOMODCACHE,若没把该目录加到 cache key 中(如 GitHub Actions 的actions/cache),每次 job 都是全新目录,等于没缓存 - 推荐做法:用 workspace-relative 路径,如
$(pwd)/.go-modcache,再配合 cache action 显式缓存该路径
另外,GOMODCACHE 不影响 go mod download 的行为逻辑,只改变存放位置;它也不影响 replace 或 require 的解析顺序——这些都由 go.mod 和 go.sum 决定。
真正要小心的是多用户共享机器场景:不同用户设了相同 GOMODCACHE 路径,可能因权限冲突导致 go mod 报错 permission denied,这时候得加用户隔离,比如路径里嵌入 $USER。











