golangci-lint 2.15 升级后 exhaustive 配置字段变更:explicit-exhaustive-switch/map 合并为 explicit-exhaustive,check: map 改为 check: mapliteral;ignore-enum-members/types 分别改为 ignore-constants/types,值须为字符串切片;check 必须明确指定 switch/mapliteral/typeswitch;配置文件名必须为 .golangci.yml、与 go.mod 同目录、缩进仅用空格;CI 中 --fast 模式会跳过 exhaustive;需清除旧缓存并删除所有 golint 相关配置。

golangci-lint 2.15 升级后 exhaustive 配置报错或静默失效
升级到 2.15.0 后,exhaustive 检查器的配置字段已变更,旧配置不会报错但会被忽略——比如 explicit-exhaustive-switch 和 explicit-exhaustive-map 已被合并为 explicit-exhaustive;check: map 必须改为 check: mapliteral。若仍沿用旧键名,工具会跳过该检查项,不提示、不报错、不生效。
常见错误现象:golangci-lint run 不再报告枚举未穷尽的 switch,但代码确实漏了分支;配置文件里写了 ignore-enum-members 却没生效。
-
ignore-enum-members→ 改为ignore-constants,且值必须是字符串切片(如["Unknown", "Unused"]),不能是单个字符串 -
ignore-enum-types→ 改为ignore-types,同样要求切片格式 - 检查对象类型现在明确分三类:
switch、mapliteral、typeswitch,需在check下分别声明,不能笼统写check: true
.golangci.yml 文件存在但 golangci-lint run 完全不启用新 linter
配置文件名、位置、缩进任一出错,都会导致整个配置被跳过——工具不会警告,而是退回到默认启用集(仅 govet、errcheck 等少数几个)。
必须确认三点:
立即学习“go语言免费学习笔记(深入)”;
- 文件名严格为
.golangci.yml(不是.golangci.yaml、golangci.yml或带 BOM 的 UTF-8 文件) - 文件与项目
go.mod在同一目录;monorepo 中每个 module 都要单独放一份 - YAML 缩进只能用空格,
linters-settings和run是顶层字段,不是linters的子项
CI 中尤其容易踩坑:别依赖自动发现,必须显式传参 golangci-lint run --config=.golangci.yml。
升级后 CI 报大量新错误,但本地 run 没反应
这不是配置失效,而是环境差异暴露了隐藏问题。2.15 把 exhaustive 划入 slow 分组,若 CI 流水线按 --fast 模式运行,它会被跳过;但某些 CI 脚本可能误启用了全部 linter,而本地没开 exhaustive 或 staticcheck。
排查重点:
- 检查 CI 是否加了
--fast:该模式默认禁用所有slow类检查器,包括新版exhaustive - 确认本地和 CI 的 Go 版本是否一致(≥ 1.21),泛型分析行为不同会导致
staticcheck报错数波动 - CI 中
GOLANGCI_LINT_CACHE若指向旧版本缓存路径,可能复用过期结果;建议清空或换路径
旧版 golint 配置残留引发冲突
golint 已归档多年,但部分老配置仍含 linters.enable: ["golint"] 或 linters.disable: ["golint"]。2.15 不再识别该名称,会静默忽略整条指令,进而导致预期禁用的 linter 实际被启用(或反之)。
正确做法:
- 配置中彻底删除所有含
golint的行 - 用
revive替代:它支持自定义规则,且能兼容golint的多数风格检查逻辑 - 若曾用
//nolint:golint注释压制,需批量替换为//nolint:revive,否则压制失效
最易被忽略的是多 module 项目里某子模块的配置没同步更新,导致部分包仍走默认规则——这种局部失效很难一眼发现,必须逐 module 核对 .golangci.yml 内容和实际生效的 linter 列表。


















