Golang Lint
Samuel BertheCommunityCreated by samberDistributed by Samuel Berthe
- Skill
- Tool integration
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a comprehensive framework for integrating golangci-lint into Go development workflows. It covers the configuration of the .golangci.yml source of truth, best practices for suppressing warnings with justified //nolint directives, and strategies for incremental adoption on legacy codebases. The skill acts as a Go code quality engineer, offering guidance on selecting linters, interpreting output, and automating fixes to maintain high standards for correctness, performance, and security.
What it does
- Configures and manages .golangci.yml for consistent project-wide linting.
- Provides commands for running linters, auto-fixing issues, and formatting code.
- Enforces strict rules for //nolint directives to ensure suppressions are documented and intentional.
- Offers strategies for parallelizing legacy codebase cleanup using specialized sub-agents.
- Helps interpret linting output to identify and resolve correctness, style, and security issues.
- Provides a reference for linter categories including security, performance, and complexity.
When to use it
- When setting up code quality tooling for a new or existing Go project.
- When configuring or updating .golangci.yml settings.
- When needing to suppress a false positive lint warning using proper syntax.
- When cleaning up a legacy codebase and requiring a structured, parallelized approach.
- When troubleshooting linting errors like deadline timeouts or linter conflicts.
Advantages
- Centralizes linting configuration as a single source of truth.
- Promotes a proactive development workflow rather than post-hoc cleanup.
- Ensures security and correctness linters are prioritized and never ignored.
- Provides clear, actionable patterns for suppressing warnings without losing traceability.
- Facilitates incremental adoption of linting in large, complex projects.
Usage examples
- “Configure my project to use the recommended golangci-lint settings.”
- The agent will generate or update the .golangci.yml file with the recommended production-ready linter configuration.
- “I have a legacy codebase with too many lint errors. How do I start cleaning it up?”
- The agent will suggest setting issues.new-from-rev to focus on new code and provide a plan for parallelizing the cleanup of existing issues.
- “How do I suppress this errcheck warning for a fire-and-forget log sync?”
- The agent will provide the correct //nolint:errcheck directive with a required justification comment.
- “Run the linters and auto-fix everything that is possible.”
- The agent will execute golangci-lint run --fix ./... to automatically resolve fixable style and quality issues.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/samber/golang-lint/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip golang-lint.zip -d .agents/skills
Documentation by samber
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.
Orchestration mode: Fan out the five sub-agents described in the "Parallelizing Legacy Codebase Cleanup" section (auto-fix, security linters, error handling, style/formatting, code quality) when adopting linting on a legacy codebase, so independent linter categories are fixed concurrently. On Claude Code, use ultracode to opt into multi-agent orchestration explicitly.
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 --fixon 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.
Dependencies:
golangci-lint:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
Go Linting
Overview
golangci-lint 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 48 linters enabled.
Quick Reference
# Run all configured linters
golangci-lint run ./...
# Auto-fix issues where possible
golangci-lint run --fix ./...
# Format code (golangci-lint v2+)
golangci-lint fmt ./...
# Run a single linter only
golangci-lint run --enable-only govet ./...
# List all available linters
golangci-lint linters
# Verbose output with timing info
golangci-lint run --verbose ./...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.
// Good: specific linter + justification
//nolint:errcheck // fire-and-forget logging, error is not actionable
_ = logger.Sync()
// Bad: blanket suppression without reason
//nolint
_ = logger.Sync()Rules:
//nolint directives MUST specify the linter name:
//nolint:errchecknot//nolint//nolint directives MUST include a justification comment:
//nolint:errcheck // reasonThe
nolintlintlinter enforces both rules above — it flags bare//nolintand missing reasonsNEVER suppress security linters (gosec, 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
Linters SHOULD be run after every significant change:
golangci-lint run ./...Auto-fix what you can:
golangci-lint run --fix ./...Format before committing:
golangci-lint fmt ./...Incremental adoption on legacy code: set
issues.new-from-revin.golangci.ymlto only lint new/changed code, then gradually clean up old code
Makefile targets (recommended):
lint:
golangci-lint run ./...
lint-fix:
golangci-lint run --fix ./...
fmt:
golangci-lint fmt ./...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:
path/to/file.go:42:10: message describing the issue (linter-name)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 // reasonif it's a false positiveUse
golangci-lint run --verbosefor additional context and timing
Common Issues
| Problem | Solution |
|---|---|
| "deadline exceeded" | Set or increase run.timeout in .golangci.yml; golangci-lint v2 defaults to no timeout (0) |
| 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 paths with linters.exclusions.paths / formatters.exclusions.paths |
Parallelizing Legacy Codebase Cleanup
When adopting linting on a legacy codebase, use up to 5 parallel sub-agents to fix independent linter categories simultaneously:
Sub-agent 1: Run
golangci-lint run --fix ./...for auto-fixable issuesSub-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-integrationskill for CI pipeline with golangci-lint-action→ See
samber/cc-skills-golang@golang-code-styleskill for style rules that linters enforce→ See
samber/cc-skills-golang@golang-securityskill for SAST tools beyond linting (gosec, govulncheck)→ See
samber/cc-skills-golang@golang-continuous-integrationskill for automated AI-driven code review in CI using these guidelines
Files
- ATTRIBUTION.mdAdded by AutoGineer890 B
- LICENSELicence file added by AutoGineer1.0 KiB
- SKILL.md7.3 KiB
- assets/.golangci.yml7.1 KiB
- evals/evals.json15.8 KiB
- references/linter-reference.md8.1 KiB
- references/nolint-directives.md2.5 KiB
references/linter-reference.md
Linter Reference
golangci-lint v2 uses a .golangci.yml with version: "2" at the project root.
Key sections of .golangci.yml:
run— concurrency, timeout, test inclusion, directory exclusionslinters.enable/linters.disable— which linters are activelinters.settings— per-linter thresholds and optionsformatters— code formatters (gofmt, gofumpt)issues— output limits, exclusion rules
To add a linter: add it to linters.enable and optionally configure it in linters.settings.
To disable a linter: move it to linters.disable with a comment explaining why.
Table of Contents
Linter Categories
Correctness & Safety
Style & Readability
Complexity
Performance
Security & Resources
Logging
Testing
Modernization & Meta
Formatting
Linter Categories
The recommended configuration enables linters across these domains:
| Domain | Linters | Catches |
|---|---|---|
| Correctness | govet, staticcheck, unused, errcheck, errorlint, nilerr, forcetypeassert, copyloopvar, durationcheck, reassign | Bugs, unchecked errors, stdlib misuse |
| Style | gocritic, revive, wsl_v5, whitespace, godot, misspell, dupword, predeclared, errname, asciicheck | Readability, naming, consistency |
| Complexity | gocyclo, nestif, funlen, dupl | Overly complex or duplicated code |
| Performance | perfsprint, unconvert, ineffassign, goconst | Conversions, string ops, dead assigns |
| Security | gosec, bidichk, bodyclose, noctx, containedctx, fatcontext, sqlclosecheck, rowserrcheck | Security issues, resource leaks (HTTP, SQL) |
| Logging | sloglint, loggercheck | Structured log consistency |
| Testing | thelper, paralleltest, testifylint, usetesting | Test hygiene and best practices |
| Modernization | modernize, exptostd, intrange, usestdlibvars, exhaustive, nolintlint | Modern Go idioms, lint hygiene |
| Formatting | gofmt, gofumpt | Code formatting |
All linters are enabled in the recommended .golangci.yml, organized by domain.
Correctness & Safety
govet — Go's built-in checker: copylocks, printf format mismatches, struct tag validation, context stored in structs, unreachable code, nil dereferences
staticcheck — Extensive static analysis: deprecated APIs, common mistakes, unnecessary code, simplifications, misuse of standard library
unused — Detects unused variables, functions, types, and struct fields
errcheck — Ensures all error returns are checked, including type assertions (configured with
check-type-assertions: true)nilerr — Detects returning nil error when
erris non-nil (common source of silent failures)forcetypeassert — Flags type assertions without the comma-ok check (
v := x.(T)instead ofv, ok := x.(T))copyloopvar — Detects loop variable copy issues (Go 1.22+)
errorlint — Enforces correct use of
errors.Is/errors.Asand%wwrapping (Go 1.13+ error wrapping)durationcheck — Detects
time.Duration * time.Durationmultiplication bugs (e.g.,2 * time.Second * time.Minuteproduces nanoseconds squared, not seconds)reassign — Detects reassignment of package-level variables outside
init(), which hides state mutations
Style & Readability
gocritic — Opinionated style checks: unnecessary conversions, range copies, append-assign patterns, redundant code
revive — Naming conventions for exported types, unexported returns, receiver naming, error naming, stuttered package names
wsl_v5 — Whitespace and blank line rules for visual grouping and readability
whitespace — Detects trailing whitespace and unnecessary blank lines in function bodies
godot — Ensures exported-symbol comments end with a period
misspell — Catches common English misspellings in identifiers and comments
predeclared — Flags shadowing of Go built-in identifiers (e.g., naming a variable
len,cap,error)errname — Enforces error naming conventions: error types suffixed with
Error(e.g.,DecodeError), error variables prefixed withErr(e.g.,ErrNotFound)dupword — Detects duplicate words in comments and strings (e.g., "the the", "is is") — often copy-paste artifacts
asciicheck — Flags non-ASCII identifiers that enable homoglyph/trojan source attacks (visually identical but different Unicode codepoints)
Complexity
gocyclo — Cyclomatic complexity threshold (configured: 13). Functions exceeding this should be split
nestif — Detects deeply nested if/else chains that harm readability
funlen — Function length limits (configured: 120 lines, 80 statements)
dupl — Code duplication detection (configured: 100 token threshold)
Performance
perfsprint — Suggests faster alternatives to
fmt.Sprintf(e.g.,strconv.Itoainstead offmt.Sprintf("%d", n))unconvert — Detects unnecessary type conversions (e.g.,
int(x)whenxis alreadyint)ineffassign — Detects assignments to variables that are never subsequently read
goconst — Detects repeated string/number literals that should be extracted to constants (configured: min 3 chars, min 4 occurrences)
Security & Resources
gosec — Security scanner: SQL injection, hardcoded credentials, weak crypto, path traversal, unsafe usage, and 50+ other rules. The primary SAST tool in the config — never suppress without strong justification.
bidichk — Detects dangerous bidirectional Unicode sequences (CVE-2021-42574 trojan source attack — code that looks safe but executes differently)
noctx — Detects HTTP requests sent without
context.Context(prevents proper timeouts and cancellation)containedctx — Flags
context.Contextstored in struct fields instead of passed as a parameter (anti-pattern per Go docs)fatcontext — Detects
context.WithValue/WithCancelin loops, creating unbounded context chains that grow each iteration and cause memory leaksbodyclose — Ensures HTTP response bodies are closed (unclosed bodies leak connections)
sqlclosecheck — Ensures
sql.Rowsandsql.Stmtare closed after userowserrcheck — Ensures
sql.Rows.Err()is checked after iteration
Logging
sloglint — Enforces consistent
log/slogcode style: proper key-value pairing, message formatting, and level usageloggercheck — Validates key-value pair formatting for structured loggers (zap, slog, logr) — detects odd numbers of args, missing keys
Testing
thelper — Ensures test helpers call
t.Helper()so failures report the correct call siteparalleltest — Detects tests and subtests missing
t.Parallel()callstestifylint — Enforces testify best practices (e.g.,
assert.Equal(t, expected, actual)overassert.True(t, expected == actual))usetesting — Suggests
t.Setenv/t.TempDirinstead ofos.Setenv/os.MkdirTempin tests (automatic cleanup, proper isolation)
Modernization & Meta
modernize — Detects code that can be rewritten using newer Go features (requires golangci-lint v2.6.0+)
exptostd — Detects
golang.org/x/exp/functions that now have stdlib equivalents (e.g.,slices,maps,cmppackages added in Go 1.21)intrange — Suggests
range Nover C-stylefor i := 0; i < N; i++loops (Go 1.22+)usestdlibvars — Replaces hardcoded strings/numbers with stdlib constants (e.g.,
http.MethodGetinstead of"GET")exhaustive — Ensures switch statements on enum types cover all possible values
nolintlint — Enforces proper
//nolintdirective usage: requires linter name and justification comment (configured withrequire-explanationandrequire-specific)
Formatting
Formatters run via golangci-lint fmt ./...:
gofmt — Standard Go formatter (canonical formatting)
gofumpt — Stricter formatter with extra rules (configured with
extra-rules: true): consistent empty lines, grouped imports, simplified code patterns
Requirements and compatibility
Written for: Claude Code, OpenAI Codex
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Declares allowed tools, Claude Code frontmatter
The author says: Designed for Claude Code, Codex or similar harness, and for projects using Golang.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- samber
- Publisher
- Samuel Berthe (Community)
- Distributed by
- Samuel Berthe
- Source
- samber/cc-skills-golang · skills/golang-lint · commit bb1d43d
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by samber or Samuel Berthe.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download golang-lint.zip