go mod download 默认下载到 gomodcache 指向的目录(通常为 $gopath/pkg/mod 或 $home/go/pkg/mod),不写入项目目录、vendor/ 或 $gopath/src;实际路径应以 go env gomodcache 输出为准。

go mod download 下载到哪儿?先看 GOMODCACHE 而不是 GOPATH
它不往 $GOPATH/src 写,也不进项目目录或 vendor/;实际落盘位置由 GOMODCACHE 环境变量决定,而这个值通常等于 $GOPATH/pkg/mod(如果设置了 GOPATH)或 $HOME/go/pkg/mod(Go 1.16+ 默认未设 GOPATH 时)。别凭经验猜路径,直接运行:go env GOMODCACHE
这才是真实缓存根目录。
常见误区是认为改了 GOPATH 就能控制下载位置——其实 GOMODCACHE 才是 go toolchain 实际使用的路径,GOPATH 只是它的 fallback 基础。两者可能不同,尤其在 CI 环境或自定义工作区中。
pkg/mod 目录结构:模块名 + 版本号 → 文件系统路径
每个依赖模块的每个版本都单独存为一个子目录,命名规则严格:
– 模块路径全部转为小写(github.com/AwesomeLib → github.com/awesomelib)
– 版本号带 v 前缀(v1.2.3),大版本 >1 时还含斜杠(github.com/go-playground/validator/v10 → github.com/go-playground/validator@v10.15.0)
– 最终路径形如:$GOMODCACHE/github.com/awesomelib@v1.2.3/
该目录下是完整解压后的源码(含 .go 文件),但不包含 .git 或构建产物;go build 时直接读取此处,而非远程仓库。
注意:pkg/mod/cache 是另一层内部缓存(用于加速下载和校验),用户无需也不应直接操作它。
为什么不能手动删 pkg/mod 里的某个模块子目录?
因为 go mod download 下载后会写入校验和记录到 go.sum,且本地缓存与 go.sum 强绑定。手动删掉某个 @vX.Y.Z 子目录会导致后续 go build 或 go list 报错:missing module github.com/xxx/yyy@v1.2.3
或更隐蔽的:verifying github.com/xxx/yyy@v1.2.3: checksum mismatch
在 Go 中使用 google/wire 实现编译时依赖注入——wire.NewSet、wire.Build、wire.Bind(接口→实现)、wire.Struct、wire.Value、wire.Interface
正确清理方式只有一种:go clean -modcache
它会清空整个 GOMODCACHE 并重置校验状态,之后再 go mod download 或 go build 会重新拉取并验证所有依赖。
顺带提醒:go mod vendor 生成的 vendor/ 目录是独立副本,删 pkg/mod 不影响 vendor,但下次 go mod vendor 会重新从缓存拉取 —— 如果缓存已被清空,就得联网重下。
离线构建可行吗?关键看 go.sum 和缓存是否完整
执行完 go mod download 后能否断网构建,取决于两个条件:
– go.mod 中所有 require 行(包括 // indirect 标记的)对应模块,是否都已成功下载并校验通过
– go.sum 中每条记录是否都有对应物理目录(即 GOMODCACHE 下存在该 @vX.Y.Z 子目录)
容易漏掉的情况:
– 项目用到了某间接依赖的特定功能,但该依赖未被显式 require,仅靠 go build 推导出来;此时 go mod download 默认不拉它(除非加 -d 参数)
– 某依赖在 go.sum 里有记录,但因网络中断未完成下载,pkg/mod 下缺目录,go build 会当场失败,而不是静默跳过
验证是否真离线可用,最可靠方式是:go clean -modcache && go mod download && go build -o ./tmp/main ./...
全程不碰外网,失败就说明有漏。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










