golangci-lint 配置仅在与 go.mod 同级的 .golangci.yml 文件中生效;多 module 项目需每个 module 单独配置,CI 和 IDE 中均须显式指定 --config=.golangci.yml 才启用完整规则。

golangci-lint 配置文件在哪找才生效
配置只在 go.mod 所在目录下有效的 .golangci.yml 文件中起作用;放在父目录、子目录或写成 .golangci.yaml 都会被忽略。
多 module 项目(比如 monorepo)必须每个 module 单独放一份 .golangci.yml,根目录的配置不会继承下去。CI 脚本里运行时也得显式加 --config=.golangci.yml,否则默认用内置最小集(仅 govet 和 errcheck)。
- VS Code 中需在设置里勾选「使用配置」并填对路径,否则可能缓存旧规则
- GoLand 同理:必须在 Go | 静态分析器 设置页勾选「使用配置」,再指定路径
- 编辑器里看到的波浪线,和
golangci-lint run输出不一致?八成是 IDE 没读到配置,或读错了位置
命令行参数、配置文件、默认值谁优先
命令行参数 > .golangci.yml > 内置默认值,但有例外:某些字段(如 run.skip-dirs)是合并行为,不是覆盖。
比如你在配置里写 skip-dirs: ["vendor"],又在命令行传 --skip-dirs=testdata,最终会跳过 vendor 和 testdata 两个目录;但 linters.enable 是完全替换,命令行传 --enable=staticcheck 就只开这一个 linter,不管配置里写了啥。
-
--tests必须显式传,否则_test.go文件永远不检查 -
--timeout会覆盖配置里的run.timeout,超时直接中断,不等所有 linter 完成 -
--fix不受配置控制,只要 linter 支持(如goimports、revive),就能自动修,但staticcheck这类不支持 fix 的不会动
为什么改了 linters-settings 却没效果
因为很多 linter 的行为开关不在 linters-settings 下,而是在各自独立的配置块里,比如 errcheck 的 exclude-functions 必须写在 errcheck: 一级下,而不是塞进 linters-settings.errcheck。
更常见的是字段名拼错:staticcheck 的禁用规则叫 checks(如 -SA1019),不是 disable;govet 的 shadow 检查要关,得写 govet: disable: ["shadow"],写成 disable-all: true 反而会把有用检查也关掉。
-
unused的check-exported默认为true,想让它忽略未导出函数,得设为false,且必须写在unused:块里 -
revive规则名区分大小写,exported-rule-name写成ExportedRuleName就不生效 - 所有正则类配置(如
exclude-rules)的path和text是“且”关系,不是“或”,匹配不上任意一个就跳过该条规则
测试文件检查必须手动解绑两层限制
默认情况下 _test.go 文件被双重屏蔽:一是 run.skip-files 默认含 .*_test\.go 正则,二是多数 linter(如 errcheck)在测试上下文中主动降权或跳过。
要真正启用测试检查,必须同时做两件事:清空 skip-files(设为 [] 或明确排除其他路径),并在对应 linter 配置里调低敏感度,比如:
errcheck: exclude-functions: ["t.Fatal", "t.Errorf", "log.Fatal"]-
govet: disable: ["shadow"](避免for _, tt := range tests报 shadow) - 只开
staticcheck、gosimple、unused这三个误报率低的 linter,全量开启只会让 CI 慢且告警失焦
漏掉其中任一环,_test.go 就还是静默状态——这不是 bug,是设计使然。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











