团队统一规范的核心是确保所有人看到同一份配置、执行同一套检查、收到一致反馈;必须将.golangci.yml提交至仓库根目录,显式声明version: "2",严格管理linters.enable/disable、路径排除、超时等配置,并在CI中禁用--fast、设置issues.exit-code: 1,编辑器需标准集成且依赖项目根目录下的配置文件。

团队统一规范的核心不是配多少规则,而是让所有人看到同一份配置、执行同一套检查、失败时收到一致反馈。 其他所有技巧——比如自定义规则、IDE 插件联动、CI 卡点——都只是支撑这个目标的手段。偏离这点,配置再“严格”也形同虚设。
必须提交 .golangci.yml 到仓库根目录
这是唯一能确保成员本地和 CI 行为一致的硬性要求。任何“我本地装了最新版所以不用配”的想法都会导致误报不一致、规则漏启用、甚至 golangci-lint 直接 fallback 到默认规则集(它默认启用几十个 linter,其中不少已被团队明确禁用)。
-
.golangci.yml必须在 Git 里可见、可审查、可 diff;禁止只存在开发者本地或 CI 脚本里 - 必须显式声明
version: "2"—— golangci-lint v2 的 schema 和 v1 不兼容,没这行就等于没配 - 团队共用的规则开关(如禁用
errcheck或启用nilaway)必须写死在linters.enable/linters.disable列表中,不能依赖enable-all: true - 路径排除(如
skip-dirs)、超时(run.timeout)、忽略规则(issues.exclude-rules)也必须集中管理,避免各人本地 patch
CI 中必须显式禁用 --fast 并设 issues-exit-code: 1
CI 里 golangci-lint 报错却仍通过构建,90% 是因为这两个配置缺失。--fast 会跳过部分 analyzer(尤其是基于 go/types 的深度检查),而 issues-exit-code: 1 缺失会导致即使发现 100 个问题,退出码仍是 0,Git 服务器直接放行 PR。
- GitHub Actions 示例中,
args字段必须不含--fast,推荐显式加--no-fast -
.golangci.yml顶层需有issues:段,并包含exit-code: 1(注意不是issues-exit-code,那是旧版字段名) - CI job 中不要用
|| true或set +e吞掉错误,否则 lint 失效等同于没加
Sublime / VSCode 等编辑器必须走标准集成路径
编辑器插件不会自动识别你写的任意命令行工具,也不会读取非标准格式输出。想让 golangci-lint 在保存时实时报错,就得满足它的协议约定。
- Sublime:必须安装
SublimeLinter+SublimeLinter-contrib-golangcilint,且系统 PATH 中的golangci-lint版本要与项目.golangci.yml兼容(v2 配置无法被 v1 二进制读取) - VSCode:必须在
.vscode/settings.json中显式设置"go.lintTool": "golangci-lint",并确保其输出是file:line:col: message格式(默认符合,但若加了--out-format=json就会静默失效) - 所有编辑器都依赖项目根目录下的
.golangci.yml—— 如果你把它放在config/linters/下却不 symlink,编辑器就看不到
自定义规则落地难的本质是流程缺位,不是技术不会写
写一个检查 os.Open 忘记 defer f.Close() 的 analyzer 很快,但真正卡住的是:谁来维护它?误报了怎么反馈?CI 报了但开发者说“这个 case 确实安全”,该信谁?
- 自定义 linter 必须注册到
.golangci.yml的linters-settings段,并在linters.enable显式列出名字,否则golangci-lint根本不加载 - 误报高发的规则(如只用
go/ast分析返回值却不管类型)必须升级到go/types,否则会被开发者迅速屏蔽 - 每个自定义规则旁必须附带
//nolint:rule-name的使用说明和审批流程,否则团队会用全局//nolint绕过整条规则 - 最易被忽略的一点:所有规则的“例外场景”必须文档化,写进团队 Wiki 或
golangci-strict.md这类权威文档里,而不是靠口头约定
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











