go mod tidy只删除两类模块:既未被任何.go文件import语句引用,也未被其他已保留模块间接依赖的模块;它无法识别反射调用、配置驱动、测试专用、//go:build条件编译或//go:embed引入的依赖,需人工交叉验证。

go mod tidy 会删掉哪些模块
它只删两类:既没出现在任何 .go 文件的 import 语句中,也没被其他已保留模块间接依赖的模块。比如你执行过 go get github.com/gorilla/mux,后来删光所有 import "github.com/gorilla/mux",且没别的包依赖它,那它就会被删。
但以下情况它**不会删**,甚至可能误判:
-
// import "net/http"这类注释掉的导入,不算引用,对应模块可能被删 - 仅在
//go:build integration下才生效的import,当前构建未启用该 tag → 不会被识别 -
import _ "github.com/lib/pq"这种空白导入,只要没被其他包间接依赖,也会被删(除非它靠init()注册驱动) -
//go:embed或//go:generate引用的模块,tidy 完全看不见
为什么 go mod why -m xxx 比扫 go.mod 更可靠
go mod why 显示的是模块实际进入构建图的路径,不是“有没有写在 require 里”。它能告诉你这个模块到底是被主逻辑拉进来的,还是只被测试或生成代码用到。
常用判断方式:
-
go mod why golang.org/x/sync→ 若返回main module does not need module,基本可删 -
go mod why -m golang.org/x/sync -test→ 加-test才能看到是否只被*_test.go引用 - 若输出里出现
vendor/、internal/或某个子模块路径,说明它被子模块显式 require,不能单靠根目录 tidy 清理
清理后必须验证的三件事
删完不跑验证,等于白干。尤其容易漏掉交叉场景:
-
go build ./→ 确保所有cmd/子命令都能编译通过,别只测main.go -
go test ./→ 测试文件可能引入独立依赖,tidy 默认处理它们,但得确认没 break -
go list -m all | wc -l对比前后数字;再跑一次go mod graph | grep your-module-name,确认目标模块真不在图里了
如果项目支持多平台(如含 GOOS=js 构建),建议先用对应环境执行 GOOS=js go list -deps ./,看是否引入额外包——tidy 不会自动覆盖这些。
间接依赖(// indirect)能不能手动删
不能盲目删。带 // indirect 标注的模块,是你没直接 import,但被某个依赖拉进来的。删之前得确认它是不是真断链了。
安全操作步骤:
- 先运行
go mod graph | grep 'your-module',看谁还在引用它 - 用
go list -deps -f '{{if not .Standard}}{{.ImportPath}}{{end}}' ./检查当前代码树所有实际依赖路径 - 对疑似冗余的模块,临时注释掉
go.mod里那行,再执行go build ./和go test ./—— 如果失败,说明仍有隐式依赖(比如 plugin、反射、生成代码) - 像
golang.org/x/sys这类常被标准库包间接引用的模块,即使没显式 import,也不建议手动删
真正麻烦的不是 tidy 删不掉的模块,而是它删得太干净——比如你靠 JSON 配置加载插件,或者用 reflect.ImportPath 动态加载包,这些 tidy 完全看不见,删了就 panic。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











