golangci-lint装完默认仅启用govet和errcheck,staticcheck、unused等关键检查器需通过同级go.mod目录下的.golangci.yml显式启用;多module项目须每个module单独配置,CI和IDE中均需显式指定--config=.golangci.yml才生效。

golangci-lint 装完不等于开始检查——默认只开 govet 和 errcheck,staticcheck、unused 这些真正揪 bug 的检查器全关着,没配 .golangci.yml 就等于白装。
为什么 golangci-lint run 没报错却像没运行一样
根本原因是配置文件没生效或压根不存在。它不会自动启用所有 linter,也不会继承父目录配置。
-
.golangci.yml必须和go.mod在同一级目录;写成.golangci.yaml或丢在src/里都无效 - 多 module 项目(比如 monorepo)中,每个 module 都得单独放一份配置,不能只在根目录放一个
- CI 中直接跑
golangci-lint run很容易漏读配置,务必显式加参数:golangci-lint run --config=.golangci.yml - VS Code 的 Go 插件也要手动勾选「使用配置」并填对路径,否则可能沿用旧缓存或默认规则
哪些 linter 必须显式启用才真正有用
不是“建议”,而是实际项目中误报低、问题暴露率高的最小有效组合:
-
govet:查类型不匹配、死循环、变量 shadowing 等基础语义问题 -
errcheck:强制检查error是否被处理,避免静默失败 -
staticcheck:报SA1019(调用弃用 API)、SA4006(死循环)等真实风险 -
unused:发现未使用的变量、函数、import,清理技术债务 -
revive:替代已弃用的golint,支持自定义规则(如禁止_ = xxx忽略 error)
别碰 dupl(重复代码检测)和 lll(行长限制)——前者阈值难调、易误报,后者纯属风格偏好,不该卡 CI。
.golangci.yml 配置里 enable 和 disable 冲突怎么办
两者不能共存:disable 是全局禁用某些 linter,enable 是只启用列出的几个。选一个策略就行。
- 日常推荐用
enable显式声明,避免隐式继承默认集带来的意外告警 - 例如偏重简洁和可维护性,可只开:
enable: - govet - errcheck - staticcheck - unused - revive
-
staticcheck和gosimple功能有重叠,同时开可能重复报错
CI 中 golangci-lint run 太慢,怎么提速
默认会检查所有文件,包括 vendor/ 和 testdata/,但这些通常不需要 lint。
- 加
--skip-dirs或--skip-files直接跳过:golangci-lint run --skip-dirs vendor,testdata --timeout=2m - 更关键的是启用缓存:在 CI 环境中设
GOLANGCI_LINT_CACHE指向共享路径(如/tmp/golangci-cache),并确保同一 commit 不重复跑全量 -
--fast模式跳过耗时 linter(如unused),适合 pre-commit 场景,但别在 CI 主流程里用它
真正麻烦的是不同 Go 版本下 linter 行为不一致,比如 staticcheck 在 1.21 和 1.22 对泛型的检查粒度就变了——配置不是一劳永逸的事,版本升级后要验证。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











