go mod tidy 是唯一安全、可复现的清理方式,它仅删除既无显式 import 又无间接依赖的模块,不处理运行时加载、//go:embed、条件编译等隐式依赖,需人工交叉验证。

直接删 go.mod 里的 require 行是危险操作,go mod tidy 才是唯一安全、可复现的清理方式——但它只认显式 import,不认运行时加载、//go:embed 或条件编译里的依赖。
go mod tidy 到底删不删你认为“无用”的模块
go mod tidy 不是“扫描代码找没用的包”,而是做两件事:补全所有当前构建路径里实际 import 的包,并移除那些既没被任何 .go 文件引用、也没被其他已保留模块间接拉进来的模块。所以以下情况它不会删:
-
import _ "github.com/lib/pq"这种空白导入会被保留(驱动注册依赖) -
//go:build integration下的依赖,若当前没启用该 tag,tidy就当它不存在 -
//go:embed assets/引用的包,哪怕没import,tidy也看不到 - 通过
plugin.Open()或reflect.ImportPath动态加载的包,静态分析根本捕获不到
执行 tidy 前必须检查的三件事
跳过这步容易导致构建失败或运行时 panic:
- 确保所有
.go文件(包括*_test.go、main.go、gen.go)都已保存,且go build ./和go test ./全部通过 - 如果项目含代码生成逻辑(如
stringer、mockgen),先跑一遍生成命令,再tidy—— 否则生成代码里隐含的import会被忽略 - 多平台构建(如
GOOS=js)需单独验证:用对应环境执行GOOS=js go list -deps ./ | grep your-module,确认是否引入额外依赖
怎么验证某个模块真能删
仅靠 go mod tidy 输出不够,得交叉验证:
- 运行
go mod graph | grep 'your-module',看有没有其他模块还连着它;没输出,说明没人引用 - 临时注释掉
go.mod中那行require,再执行go build ./和go test ./—— 如果失败,说明仍有隐式依赖(比如 init 注册、反射调用或生成代码) - 对疑似冗余的
// indirect模块,别急着删;先查go list -deps -f '{{.ImportPath}}' ./ | grep your-module,确认是否在实际依赖树里
真正难的不是删模块,而是识别那些“没 import 却不能删”的模块——比如数据库驱动靠 import _ 注册,HTTP 中间件靠 init() 绑定,或者 protobuf 插件生成的代码悄悄拉了新依赖。这些地方一删就 panic,但 tidy 从不提醒你。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











