必须启用的5个核心linter是govet、errcheck、staticcheck、unused、revive;它们误报低、问题暴露率高,分别检查基础语义、error处理、弃用api与死循环、未使用标识符、代码风格与自定义规则,缺一不可。

装完 golangci-lint 不等于代码风格就统一了——它默认只开 govet 和 errcheck,staticcheck、unused、revive 这些真正管风格和逻辑质量的检查器全关着,没配 .golangci.yml 就等于白装。
为什么 golangci-lint run 没报错却没效果
根本原因是配置文件没生效或压根不存在。它不会自动继承父目录配置,也不会“猜”你要用哪些 linter。
-
.golangci.yml必须和go.mod在同一级目录;写成.golangci.yaml或丢在src/里都无效 - 多 module 项目(比如 monorepo)中,每个 module 都得单独放一份
.golangci.yml,不能只在根目录放一个 - CI 中直接跑
golangci-lint run很容易漏读配置,务必显式加参数:golangci-lint run --config=.golangci.yml - VS Code 的 Go 插件也要手动勾选「使用配置」并填对路径,否则可能沿用旧缓存或默认规则
必须启用的 5 个核心 linter 是什么
不是“建议”,而是实际项目中误报低、问题暴露率高的最小有效组合:
-
govet:查类型不匹配、死循环、变量 shadowing 等基础语义问题 -
errcheck:强制检查error是否被处理,避免静默失败(比如_ = os.Remove(...)) -
staticcheck:报SA1019(调用弃用 API)、SA4006(死循环)、SA9003(无用 if 条件)等真实风险 -
unused:发现未使用的变量、函数、import,清理技术债务(注意:它不检查未导出的私有符号) -
revive:替代已弃用的golint,支持自定义规则(如禁止_ = xxx忽略 error)
别碰 dupl(重复代码检测)和 lll(行长限制)——前者阈值难调、易误报,后者纯属风格偏好,不该卡 CI。
CI 里 golangci-lint 卡住或超时怎么办
常见于 GitHub Actions / GitLab CI,本质是资源没控住,不是工具本身慢。
- 加
--concurrency=2:CI 通常只有 2 vCPU,不设会争抢资源 - 加
--timeout=2m:防止单次分析无限 hang 住整条流水线 - 加
--fast:跳过goconst、gocyclo等耗时 linter,保留上面 5 个核心项即可 - 缓存
~/.cache/golangci-lint:否则每次重编译 linter,启动就慢半分钟
--fast 在 IDE 里也要开,否则编辑器会卡顿;但本地全量扫描仍建议定期去掉该 flag,跑一次深度检查。
怎么跳过某行或整个文件的检查
不是为了绕过问题,而是应对生成代码、兼容性适配等真实例外场景。
- 跳过某一行:
//nolint:gosimple(仅禁用指定 linter),或//nolint(禁用所有) - 跳过整个文件:在文件顶部第一行加
//nolint,或在.golangci.yml的exclude-files列表中声明正则,比如"\.gen\.go$"
格式化本身靠 gofmt -w . 或 go fmt -w . 就够了,它不依赖配置文件,但必须确保团队所有人用同一版本(Go 1.23+ 的 gofmt 对泛型处理更稳)。真正的风格分歧往往藏在 linter 规则边界里,比如 revive 的 exported 规则是否强制要求所有 public 函数带 godoc,这种细节才是落地时最容易扯皮的地方。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











