根本原因是$GOCACHE或$GOMODCACHE所在文件系统被挂载为只读,常见于容器、CI或NFS环境;Go会静默降级到默认路径(如/root/.cache/go-build),需显式设置可写路径并验证目录权限。

Go build 时提示 permission denied 或 cannot write to $GOCACHE
根本原因不是 Go 本身权限问题,而是 $GOCACHE(默认 $HOME/Library/Caches/go-build macOS / $HOME/.cache/go-build Linux)所在文件系统被挂载为只读。常见于容器环境、CI runner、受限沙箱或 NFS 挂载目录。
Go 在构建时会缓存编译对象(.a 文件)、测试结果和依赖解析结果,这些都写入 $GOCACHE;一旦该路径不可写,go build、go test 甚至 go list 都可能失败。
- 临时解决:用
go build -a绕过缓存(但极慢,不推荐长期使用) - 正确做法:显式设置可写的
$GOCACHE目录,例如export GOCACHE=/tmp/go-cache - 若在容器中,确保
/tmp或挂载的 volume 具有写权限,并在启动前设置该变量 - 注意:
$GOCACHE不影响模块下载(那是$GOPATH/pkg/mod),但影响编译速度和增量构建能力
go mod download 失败提示 no write permissions for module cache
这个错误其实误导性很强——它真正指向的是模块根缓存目录 $GOPATH/pkg/mod(或 $GOMODCACHE),而非 $GOCACHE。当 Go 尝试解压 downloaded 的 zip 包到本地模块缓存时,发现目标路径只读,就会报这个错。
在 Go 中使用 google/wire 实现编译时依赖注入——wire.NewSet、wire.Build、wire.Bind(接口→实现)、wire.Struct、wire.Value、wire.Interface
- 检查当前模块缓存位置:
go env GOMODCACHE(通常等于$GOPATH/pkg/mod) - 解决方案:设置
GOMODCACHE到可写路径,如export GOMODCACHE=/tmp/go-mod-cache - 必须同时设置
GOPATH(如果未设,默认是$HOME/go),否则GOMODCACHE可能被忽略 - 若使用
go install安装二进制,还可能涉及$GOBIN,一并确认其可写
Docker 中构建 Go 项目时反复遇到只读错误
典型场景:Dockerfile 使用 FROM golang:alpine 或 scratch 基础镜像,且挂载了 host 的只读 volume(比如 CI 系统自动挂载源码目录为 ro),导致 /go 或 /tmp 被意外限制。
立即学习“go语言免费学习笔记(深入)”;
- 不要依赖默认
$HOME:Alpine 中$HOME是/root,而某些运行时会把 rootfs 挂为只读;显式设置ENV GOCACHE=/tmp/gocache和ENV GOMODCACHE=/tmp/gomodcache - 在
RUN指令前加mkdir -p /tmp/gocache /tmp/gomodcache,避免因目录不存在触发其他权限逻辑 - 避免在
WORKDIR上做构建:如果WORKDIR是只读挂载点,go build -o输出到该目录也会失败;改用go build -o /tmp/app - 多阶段构建中,build 阶段用完整镜像(如
golang:1.22),final 阶段才切scratch或alpine,这样缓存只在 build 阶段生效,不影响运行时
为什么设置了 GOCACHE 还是写到了 /root/.cache/go-build?
因为 Go 会 fallback 到默认路径,当显式设置的路径不可写(比如目录不存在且无创建权限、父目录只读、SELinux/AppArmor 限制等),Go 不报错,而是静默降级回默认路径——这就埋下了隐患。
- 验证是否生效:
go env GOCACHE必须输出你设置的路径;再执行go build -x查看日志中-cachedir=...是否匹配 - 检查父目录权限:
ls -ld /tmp(或你设的路径父级),确保执行用户有w权限 - 在容器中,
/tmp有时被 tmpfs 挂载但 size 限制太小(如 64M),导致写入中途失败;可用df -h /tmp确认 - 最稳妥方式:构建前先
mkdir -p $GOCACHE && chmod 700 $GOCACHE,排除目录初始化问题
go env 看清所有相关变量,再 ls -ld 确认路径真实可写,比猜更省时间。

















