go mod tidy 是同步器,将 go.mod 与代码实际 import 的包对齐:添加缺失依赖、删除未使用依赖,并更新 go.sum;它不升级版本、不解决冲突、不清理缓存或源文件。

go mod tidy 到底在做什么?
go mod tidy 不是“升级依赖”或“智能选版本”的命令,它是个**同步器**:把 go.mod 文件和当前代码里真实 import 的包对齐。它只做两件事——加缺失的、删没用的,顺便更新 go.sum 校验和。
它不会主动升级已有依赖(比如把 v1.2.0 换成 v1.3.0),也不会帮你解决多个子依赖要求不同版本的冲突(例如 A 要 logrus v1.9.3,B 要 v1.10.0,tidy 会停在 MVS 规则选出的最小可行版本,不强制统一)。
- 它扫描所有
.go文件(包括*_test.go),提取 import 路径,构建“实际使用清单” - 对比
go.mod中的require条目:清单里有但没声明 → 自动加;清单里没有但声明了 → 准备删 - 间接依赖(如你没 import C,但依赖的 B 用了 C)只要仍是运行必需,就会被保留,哪怕标记为
// indirect
为什么有时候删不掉某个包?
常见现象:go mod tidy 运行后,go.mod 里还留着一个你“明明没 import”的包。这不是 bug,而是它被判定为仍需存在:
-
_ "github.com/some/pkg"这种空白导入会被识别为“已引用”,不会删 - 测试文件(
xxx_test.go)里 import 了,即使主逻辑没用,也会保留 - 该包是另一个已保留依赖的传递依赖(A→B→C,A 用了 B,B 用了 C,C 就得留着)
-
go.mod里写了replace或exclude,tidy 尊重这些人工干预,不会擅自绕过 - 构建标签(
//go:build linux)导致某些文件未参与分析,但其中的 import 实际生效 —— tidy 看不到,就可能误判
怎么安全地清理并验证效果?
别直接跑完就提交。清理依赖的关键是“确认删得对”,而不是“删得多”:
- 先确保在项目根目录(含
go.mod的目录)下操作 - 运行
go mod tidy -v,观察输出中是否有removing unused requirement或adding module提示 - 立刻执行
go build ./和go test ./,尤其是集成测试——很多问题只在运行时暴露 - 用
go list -m all | grep "pkg-name"查看某包是否还在解析结果里;用go mod graph | grep "pkg-name"看它挂在谁下面 - 如果 CI 报错,用
git diff go.mod快速定位删了什么,再回溯代码确认是否真不需要
它不碰哪些东西?别指望 tidy 干这些活
go mod tidy 只改 go.mod 和 go.sum,其他全是“视而不见”:
- 不会清空本地模块缓存(
$GOPATH/pkg/mod)——想彻底释放空间,得手动go clean -modcache - 不会删除项目里你自己写的、但没被任何 import 引用的
.go文件(那是源码,不是依赖) - 不会处理
vendor/目录(除非加-v参数且显式启用 vendor 模式,但非常规用法) - 不会识别反射调用(
reflect.ImportPath)、//go:linkname或代码生成工具动态引入的包
依赖管理最终靠人判断,go mod tidy 只是把你的判断结果整理干净。它删得果断,也留得谨慎;信它之前,先信自己的 go build 和 go test。










