golangci-lint 默认不检查 main 包未使用变量,因启用的 unused 等 linter 为避免误报而跳过 main 包;可通过配置启用检查。

golangci-lint 为什么默认不检查 main 包里的未使用变量?
因为 golangci-lint 默认启用的 linter(如 unused)会跳过 main 函数所在包——它认为 main 包是程序入口,变量可能被 runtime 或 linker 间接引用,静态分析易误报。这不是 bug,是保守策略。
如果你确实想检查 main 包中的未使用变量(比如调试时快速清理临时代码),需要显式启用并配置:
- 在
.golangci.yml中取消注释或添加unused,并设置run: {skip-dirs: []}避免跳过main目录 - 或者用命令行临时覆盖:
golangci-lint run --enable=unused --skip-dirs="" ./... - 注意:
unused依赖 type-checking,开启后首次运行会稍慢;若项目含 cgo 或 plugin 代码,仍可能漏报
如何让 golangci-lint 只检查 Git 变更的文件?
直接用 --new 或 --new-from-rev 是最常用且可靠的方式,它基于 Git 状态过滤,不依赖 IDE 或本地构建缓存。
典型场景:CI 中只检查 PR 修改的文件,或本地提交前快速验证改动:
立即学习“go语言免费学习笔记(深入)”;
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
-
golangci-lint run --new:检查工作区中git status --porcelain标记为 modified/added 的 .go 文件 -
golangci-lint run --new-from-rev=origin/main:检查当前分支相对于origin/main的新增/修改文件(推荐用于 PR 检查) - 注意:
--new不识别重命名(R状态),也不检查已git add但未commit的 staged 删除——若需严格覆盖,建议搭配git diff --name-only HEAD...origin/main -- '*.go'+xargs
golangci-lint 报 SA1019: xxx is deprecated 却找不到调用点?
这个警告来自 staticcheck(SA1019),但它检测的是“被标记为 Deprecated 的导出标识符是否被其他包引用”,而不是你当前文件里写了什么。所以即使你的代码没显式调用,只要某个依赖包的 public API 引用了已弃用符号,且你 import 了该包,就可能触发。
排查路径:
- 先确认警告中的
xxx是哪个符号(例如http.CloseNotifier),再查它的// Deprecated:注释位置 - 用
go mod graph | grep看谁 import 了定义该符号的包(如net/http) - 重点检查间接依赖:运行
golangci-lint run -v查看完整调用链,输出里会有类似used by github.com/some/lib (via net/http)的提示 - 临时压制仅对特定导入生效:
//nolint:SA1019 // needed for legacy compat,但别加在import行上,要加在实际使用该符号的语句上方
CI 中 golangci-lint 常因超时失败,怎么稳住?
超时通常不是因为规则多,而是并发分析时内存暴涨或 I/O 卡在 vendor / go.sum / module cache。关键不是砍规则,而是控制资源边界。
实操建议:
- 设硬性超时:
golangci-lint run --timeout=3m(避免卡死整个 CI job) - 降并发:
--concurrency=2(尤其在 2c4g 的 CI runner 上,runtime.NumCPU()默认值反而容易 OOM) - 跳过 vendor:
--skip-dirs=vendor(除非你真要检查第三方代码) - 预热模块缓存:在 lint 前加
go list ./... > /dev/null,能显著减少首次分析延迟 - 注意:不要用
--fast,它跳过 type-checking 类 linter(如errcheck,govet),失去核心价值
真正难处理的是跨 module 的类型引用问题——比如你改了 internal/xxx,但 cmd/yyy 里某处隐式依赖旧签名,这种 case 往往要靠 --issues-exit-code=0 + 日志归档来兜底,没法完全自动化拦截。

















