unused linter 默认不启用,需在 .golangci.yml 的 linters.enable 中显式添加 - unused,并在命令行加 --tests 才检查测试文件;排除生成代码需用 exclude-rules 精准过滤;应禁用已废弃的 deadcode。

unused linter 默认不启用,必须显式打开
golangci-lint 的 unused linter 不在默认启用列表里,哪怕你写了 golangci-lint run ./,也不会检查未使用的变量、函数或类型。这不是漏配,是设计选择——它依赖 SSA 分析,开销略高,且和 govet 的 unusedwrite、lostcancel 等有职责区分。
要让它生效,必须在 .golangci.yml 的 linters.enable 中明确列出:
linters:
enable:
- unused
别写成 enable-all: true 就以为万事大吉——unused 属于“需手动开启”的高价值 linter,enable-all 仍可能跳过它(取决于版本,默认行为不一致)。
测试文件里的未使用变量不会被检查,除非加 --tests
_test.go 文件中的 var tt testCase、benchResult int 这类声明,默认完全逃过 unused 扫描。原因很实际:测试里常有临时变量只在调试时用,或 benchmark 中预分配但未全路径触发,误报率高。
想让 unused 覆盖测试文件,两件事缺一不可:
- 在
run区块清空skip-files,或确保没写.*_test.go - 命令行必须带
--tests参数:golangci-lint run --tests - CI 脚本中不能省略:
golangci-lint run --tests --config=.golangci.yml
漏掉 --tests,配置里写十遍 unused 也白搭——它根本不会加载测试文件。
排除生成代码或特定模式,避免误报
unused 在 protobuf 生成文件、mocks/ 目录或 swag 生成的 docs/ 里容易报一堆“未使用 struct field”,这不是 bug,是它真把那些字段当成了死代码。
用 exclude-rules 精准过滤:
issues:
exclude-rules:
- path: ".*_gen\.go"
text: "is unused"
- path: "mocks/.*"
text: "is unused"
- path: "docs/.*"
text: "is unused"
注意:text 是正则匹配报错信息原文,不是变量名;path 是相对项目根目录的路径模式;二者是“且”关系,必须同时满足才忽略。
与 staticcheck 冲突?别同时开 unused + govet 的 deadcode
unused 和 govet 的 deadcode 检查目标高度重叠(都找未导出的未使用符号),但实现机制不同:unused 更准、支持跨文件分析,deadcode 已被 Go 官方标记为 deprecated,且在 module 模式下基本失效。
建议直接禁用 deadcode,只留 unused:
linters:
disable:
- deadcode
enable:
- unused
如果还启用了 staticcheck,它内部已包含部分未使用符号检测(如 SA4006),但粒度更粗;unused 仍是唯一能精准定位 var _ = fmt.Println 这种占位符是否真被删干净的工具。
最易被忽略的是:多 module 项目中,每个 module 目录下都得有自己的 .golangci.yml,且都得显式启用 unused 并配好 --tests——根目录的配置不会向下透传。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











