go mod tidy 删除未被 import 的包,仅依据实际 import 语句判定依赖必要性,不保留注释、测试提及或备用包;它扫描所有 .go 文件构建使用清单,对比 go.mod 增删依赖,并保留空白导入、反射调用、replace/exclude 干预等情况。

go mod tidy 删除包,是因为它严格按“代码是否实际 import”来判断依赖必要性。 它不看注释、不猜意图、不保留备用项——只认真实出现在 .go 文件里的 import 语句。只要没被导入,哪怕包还在文档里写着、测试里提过、或者你“以后可能会用”,它都会删。
它怎么知道该删哪个包?
tidy 扫描项目中所有 .go 文件(包括测试文件 *_test.go),逐行解析 import 声明,构建一张“当前正在用的模块清单”。然后对比 go.mod 中的 require 列表:
- 清单里有、
go.mod里没有 → 自动添加(含版本推导) - 清单里没有、
go.mod里却有 → 标记为“未使用”,准备删除 - 间接依赖(比如 A 依赖 B,B 依赖 C)只要 C 没被任何
import直接或间接触发到,且没被其他显式 require 锁定,tidy 也可能移除 C(尤其在-compat版本较新时)
为什么有时候删了但本地文件还在?
go mod tidy 只改 go.mod 和 go.sum,不碰磁盘上的模块缓存。你看到的 $GOPATH/pkg/mod 里残留的包,是 Go 的全局模块缓存,供所有项目复用。删了 go.mod 不等于清缓存。
- 想彻底清理无用缓存:运行
go clean -modcache(注意:这会清空所有项目共享的缓存,下次构建可能要重下) - 只想删某个特定包:手动进入
$GOPATH/pkg/mod,找对应路径如github.com/some/pkg@v1.2.3文件夹删掉 - 日常建议:缓存留着更高效;除非磁盘告急或怀疑缓存污染,否则不用主动清
哪些包 tidy 可能“误放一马”?
不是所有没 import 的包都会被删。以下情况 tidy 通常保留:
- 用了空白导入(
_ "github.com/xxx"):即使没调用,也算“被引用” - 包被
//go:linkname或反射等非常规方式使用:tidy 看不到,但运行时需要 - 模块被
replace或exclude显式干预过:tidy 尊重这些声明,不会擅自绕过 - 主模块自身路径写错(如拼错 github.com/cloudwego → github.com/couldwego):导致 import 路径和模块路径不匹配,tidy 可能无法正确识别依赖关系,甚至报错
删完一定要验证
删包不是终点,编译和测试才是确认安全的关键:
- 运行
go build ./...看是否全部通过 - 跑
go test ./...,尤其关注集成测试和 e2e 测试 - 检查 CI 流水线是否绿灯;如果失败,用
git diff go.mod快速定位删了什么 - 对关键服务,建议先在预发环境部署验证,再合入主干
基本上就这些。tidy 的逻辑很朴素:代码没 import,就不该在依赖列表里。它不复杂,但容易忽略隐式引用和缓存残留。










