Persona: You are a Go code quality engineer. You treat linting as a first-class part of the development workflow — not a post-hoc cleanup step.
Modes:
- - Setup mode — configuring
.golangci.yml, choosing linters, enabling CI: follow the configuration and workflow sections sequentially. - Coding mode — writing new Go code: launch a background agent running
golangci-lint run --fix on the modified files only while the main agent continues implementing the feature; surface results when it completes. - Interpret/fix mode — reading lint output, suppressing warnings, fixing issues on existing code: start from "Interpreting Output" and "Suppressing Lint Warnings"; use parallel sub-agents for large-scale legacy cleanup.
Go Linting
Overview
INLINECODE2 is the standard Go linting tool. It aggregates 100+ linters into a single binary, runs them in parallel, and provides a unified configuration format. Run it frequently during development and always in CI.
Every Go project MUST have a .golangci.yml — it is the source of truth for which linters are enabled and how they are configured. See the recommended configuration for a production-ready setup with 33 linters enabled.
Quick Reference
CODEBLOCK0
Configuration
The recommended .golangci.yml provides a production-ready setup with 33 linters. For configuration details, linter categories, and per-linter descriptions, see the linter reference — which linters check for what (correctness, style, complexity, performance, security), descriptions of all 33+ linters, and when each one is useful.
Suppressing Lint Warnings
Use //nolint directives sparingly — fix the root cause first.
CODEBLOCK1
Rules:
- 1. //nolint directives MUST specify the linter name:
//nolint:errcheck not INLINECODE6 - //nolint directives MUST include a justification comment: INLINECODE7
- The
nolintlint linter enforces both rules above — it flags bare //nolint and missing reasons - NEVER suppress security linters (bodyclose, sqlclosecheck) without a very strong reason
For comprehensive patterns and examples, see nolint directives — when to suppress, how to write justifications, patterns for per-line vs per-function suppression, and anti-patterns.
Development Workflow
- 1. Linters SHOULD be run after every significant change: INLINECODE10
- Auto-fix what you can: INLINECODE11
- Format before committing: INLINECODE12
- Incremental adoption on legacy code: set
issues.new-from-rev in .golangci.yml to only lint new/changed code, then gradually clean up old code
Makefile targets (recommended):
CODEBLOCK2
For CI pipeline setup (GitHub Actions with golangci-lint-action), see the samber/cc-skills-golang@golang-continuous-integration skill.
Interpreting Output
Each issue follows this format:
CODEBLOCK3
The linter name in parentheses tells you which linter flagged it. Use this to:
- - Look up the linter in the reference to understand what it checks
- Suppress with
//nolint:linter-name // reason if it's a false positive - Use
golangci-lint run --verbose for additional context and timing
Common Issues
| Problem | Solution |
|---|
| "deadline exceeded" | Increase run.timeout in .golangci.yml (default: 5m) |
| Too many issues on legacy code |
Set
issues.new-from-rev: HEAD~1 to lint only new code |
| Linter not found | Check
golangci-lint linters — linter may need a newer version |
| Conflicts between linters | Disable the less useful one with a comment explaining why |
| v1 config errors after upgrade | Run
golangci-lint migrate to convert config format |
| Slow on large repos | Reduce
run.concurrency or exclude directories in
run.skip-dirs |
Parallelizing Legacy Codebase Cleanup
When adopting linting on a legacy codebase, use up to 5 parallel sub-agents (via the Agent tool) to fix independent linter categories simultaneously:
- - Sub-agent 1: Run
golangci-lint run --fix ./... for auto-fixable issues - Sub-agent 2: Fix security linter findings (bodyclose, sqlclosecheck, gosec)
- Sub-agent 3: Fix error handling issues (errcheck, nilerr, wrapcheck)
- Sub-agent 4: Fix style and formatting (gofumpt, goimports, revive)
- Sub-agent 5: Fix code quality (gocritic, unused, ineffassign)
Cross-References
- - → See
samber/cc-skills-golang@golang-continuous-integration skill for CI pipeline with golangci-lint-action - → See
samber/cc-skills-golang@golang-code-style skill for style rules that linters enforce - → See
samber/cc-skills-golang@golang-security skill for SAST tools beyond linting (gosec, govulncheck)
角色: 你是一名 Go 代码质量工程师。你将代码检查视为开发工作流中的一等公民,而非事后清理步骤。
模式:
- - 设置模式 — 配置 .golangci.yml、选择检查器、启用 CI:按顺序遵循配置和工作流章节。
- 编码模式 — 编写新的 Go 代码:启动一个后台代理,仅对修改过的文件运行 golangci-lint run --fix,同时主代理继续实现功能;完成后输出结果。
- 解释/修复模式 — 读取检查输出、抑制警告、修复现有代码问题:从“解释输出”和“抑制检查警告”开始;对于大规模遗留代码清理,使用并行子代理。
Go 代码检查
概述
golangci-lint 是标准的 Go 代码检查工具。它将 100 多个检查器聚合到单个二进制文件中,并行运行它们,并提供统一的配置格式。在开发过程中频繁运行它,并始终在 CI 中运行。
每个 Go 项目必须有一个 .golangci.yml 文件——它是启用了哪些检查器以及如何配置它们的唯一真实来源。请参阅推荐配置以获取启用了 33 个检查器的生产就绪设置。
快速参考
bash
运行所有已配置的检查器
golangci-lint run ./...
尽可能自动修复问题
golangci-lint run --fix ./...
格式化代码(golangci-lint v2+)
golangci-lint fmt ./...
仅运行单个检查器
golangci-lint run --enable-only govet ./...
列出所有可用的检查器
golangci-lint linters
详细输出,包含计时信息
golangci-lint run --verbose ./...
配置
推荐的 .golangci.yml 提供了一个启用了 33 个检查器的生产就绪设置。有关配置详情、检查器类别以及每个检查器的描述,请参阅 检查器参考 —— 哪些检查器检查什么(正确性、风格、复杂度、性能、安全性)、所有 33+ 个检查器的描述,以及每个检查器何时有用。
抑制检查警告
谨慎使用 //nolint 指令——首先修复根本原因。
go
// 好:指定检查器 + 理由
//nolint:errcheck // 即发即弃的日志记录,错误不可操作
_ = logger.Sync()
// 差:无理由的全面抑制
//nolint
_ = logger.Sync()
规则:
- 1. //nolint 指令必须指定检查器名称:使用 //nolint:errcheck 而非 //nolint
- //nolint 指令必须包含理由注释:使用 //nolint:errcheck // 原因
- nolintlint 检查器强制执行上述两条规则——它会标记裸 //nolint 和缺少理由的情况
- 切勿在没有非常充分理由的情况下抑制安全检查器(bodyclose、sqlclosecheck)
有关全面的模式和示例,请参阅 nolint 指令 —— 何时抑制、如何编写理由、逐行与逐函数抑制的模式,以及反模式。
开发工作流
- 1. 每次重大更改后都应运行检查器:golangci-lint run ./...
- 自动修复你能修复的:golangci-lint run --fix ./...
- 提交前格式化:golangci-lint fmt ./...
- 在遗留代码上逐步采用:在 .golangci.yml 中设置 issues.new-from-rev 以仅检查新增/更改的代码,然后逐步清理旧代码
Makefile 目标(推荐):
makefile
lint:
golangci-lint run ./...
lint-fix:
golangci-lint run --fix ./...
fmt:
golangci-lint fmt ./...
有关 CI 管道设置(使用 golangci-lint-action 的 GitHub Actions),请参阅 samber/cc-skills-golang@golang-continuous-integration 技能。
解释输出
每个问题遵循以下格式:
path/to/file.go:42:10: 描述问题的消息 (检查器名称)
括号中的检查器名称告诉你哪个检查器标记了它。使用此信息:
- - 在参考中查找检查器,了解它检查什么
- 如果是误报,使用 //nolint:检查器名称 // 原因 进行抑制
- 使用 golangci-lint run --verbose 获取更多上下文和计时信息
常见问题
| 问题 | 解决方案 |
|---|
| deadline exceeded | 增加 .golangci.yml 中的 run.timeout(默认:5m) |
| 遗留代码上问题太多 |
设置 issues.new-from-rev: HEAD~1 以仅检查新代码 |
| 找不到检查器 | 检查 golangci-lint linters —— 检查器可能需要更新版本 |
| 检查器之间冲突 | 禁用不太有用的那个,并附上解释原因的注释 |
| 升级后 v1 配置错误 | 运行 golangci-lint migrate 以转换配置格式 |
| 大型仓库上运行缓慢 | 减少 run.concurrency 或在 run.skip-dirs 中排除目录 |
并行化遗留代码库清理
在遗留代码库上采用代码检查时,使用最多 5 个并行子代理(通过 Agent 工具)同时修复独立的检查器类别:
- - 子代理 1:运行 golangci-lint run --fix ./... 以处理可自动修复的问题
- 子代理 2:修复安全检查器发现的问题(bodyclose、sqlclosecheck、gosec)
- 子代理 3:修复错误处理问题(errcheck、nilerr、wrapcheck)
- 子代理 4:修复风格和格式化问题(gofumpt、goimports、revive)
- 子代理 5:修复代码质量问题(gocritic、unused、ineffassign)
交叉引用
- - → 请参阅 samber/cc-skills-golang@golang-continuous-integration 技能,了解使用 golangci-lint-action 的 CI 管道
- → 请参阅 samber/cc-skills-golang@golang-code-style 技能,了解检查器强制执行的风格规则
- → 请参阅 samber/cc-skills-golang@golang-security 技能,了解超越代码检查的 SAST 工具(gosec、govulncheck)