go mod tidy无输出但依赖未下载,大概率是缓存路径错乱;需执行go clean -modcache彻底清理,再检查goproxy、gomodcache路径及replace配置是否一致。

go mod tidy 无输出但依赖没下载,大概率是缓存路径错乱
Go 模块系统会把不同来源、不同版本的模块解压到 $GOMODCACHE 下的固定路径,比如 github.com/user/repo@v1.2.3 对应 $GOPATH/pkg/mod/github.com/user/repo@v1.2.3。但如果项目曾用过本地 replace(如 replace github.com/a/b => ../b),又切回远程地址,而缓存里还留着旧的本地路径映射或损坏的 .info 文件,go mod tidy 就可能静默跳过下载——它认为“已存在”,实际却没加载进当前模块图。
验证方式:go list -m all | grep your-module 看是否显示了错误路径或空版本;再查 ls $GOMODCACHE/github.com/user/repo@v1.2.3 是否真有内容。常见误判是以为 go.mod 改了就立刻生效,其实缓存不清理,Go 仍优先读本地解压目录。
- 先运行
go clean -modcache彻底清空缓存目录(注意:这会删掉所有 zip 和源码,但保留go.mod和go.sum) - 确认
go env GOPROXY设置合理,国内建议设为https://goproxy.cn,direct - 执行
go mod download -v,观察每行开头的Fetching是否指向预期地址
私有模块拉取失败但凭证正确,往往是缓存混了多个代理源
当你在公司内网切换过 GOPROXY(比如从 proxy.golang.org 切到自建 Nexus),旧缓存里可能同时存着同一模块的两个版本:一个来自公共代理(带 checksum),一个来自私有代理(无校验)。此时 go build 会随机挑一个用,导致 checksum mismatch 或 invalid version: unknown revision。
这不是网络问题,而是缓存污染。尤其当 GOSUMDB 保持默认(sum.golang.org)时,它只校验公共代理下载的模块,对私有代理返回的内容直接放行——但缓存目录里两者共存,Go 不区分来源。
- 必须清缓存:
go clean -modcache - 清理后立即设置好环境:
GOPROXY=https://your-nexus-proxy/+GOPRIVATE=*.your-company.com+GONOSUMDB=*.your-company.com - 避免后续污染:不要在同一个
$GOPATH下混用公共和私有代理配置
多模块工作区(go.work)下依赖解析异常,根源常在缓存未隔离
go.work 文件本身不管理缓存,它只是告诉 Go “这几个目录一起算一个逻辑模块”。但所有子模块共享同一个 $GOMODCACHE。如果 A 模块 require github.com/x/y@v1.0.0,B 模块 require github.com/x/y@v2.0.0,而你之前只在 A 目录下跑过 go mod tidy,那么缓存里可能只有 v1.0.0,B 构建时就会卡住或报错。
更隐蔽的是 replace 冲突:A 的 go.mod 里 replace 了 x/y 到本地路径,B 没写 replace,但缓存里已存在那个本地路径的软链接,B 构建时可能意外复用它。
- 每个
go.work项目应配独立GOPATH和GOMODCACHE(例如export GOPATH=$PWD/.gopath) - 禁用
go env -w,所有环境变量通过 shell 导出,防止跨工作区污染 - CI 中每次构建前加
go clean -modcache,别指望go mod tidy自动补全缺失版本
只删某个模块而非全清,手动操作要避开 .info 文件陷阱
全量清理 go clean -modcache 安全但慢,尤其在 CI 或磁盘 IO 敏感场景。精细清理可行,但必须知道删什么、不能删什么:真正决定模块可用性的是 $GOMODCACHE/cache/download/ 下的 .info 文件(记录 commit hash 和校验值),不是 .zip 或解压目录。删了 .zip 而留着 .info,go mod download 会认为“已校验过”,直接跳过重下,结果还是用旧代码。
正确做法是进 $GOMODCACHE/cache/download/github.com/user/repo/@v/,删整个 v1.2.3 目录(含 v1.2.3.info、v1.2.3.zip、v1.2.3.ziphash),再 go mod download。
- 别用
rm -rf $GOMODCACHE/github.com/user/repo@v1.2.3—— 这删的是解压后目录,不影响下次下载逻辑 - 想批量清理不用的模块?用
go mod graph | awk '{print $1}' | sort -u提取当前项目真正在用的模块名,再比对ls $GOMODCACHE/cache/download下的域名目录 - 删完立刻
go mod verify,确认校验通过,而不是等构建时报错才反应过来
缓存路径错乱的问题,往往不是某一步做错,而是多步叠加后状态不可见。最危险的操作是“只清 zip 不清 info”或“在共享 GOPATH 下混用 go.work 和 replace”,这两类问题不会立刻报错,但会在某次分支切换或 CI 重跑时突然爆发,且难以复现。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











