Skip to content

Curate golangci-lint linter set beyond the v2 standard set #8

Description

@grantcarthew

Background

Project 06-linter-config-and-print-helpers.md lands .golangci.yml at the repo root with linters.default: standard — the upstream-curated five: errcheck, govet, ineffassign, staticcheck, unused. Running linters.default: all against the codebase during project review surfaced 945 issues across 47 linters. That blast radius is too large to triage as part of the print-strip project, so broader linter adoption is deferred to this follow-up.

Goal

Walk the golangci-lint v2 linter catalogue, decide keep/disable per linter, fix the findings of the ones we keep (or scope them as their own sub-issues), and commit the resulting .golangci.yml with linters.default: all plus a linters.disable list.

Scope

In scope:

  • Review each of the ~47 non-standard linters surfaced by linters.default: all and make a keep/disable decision per linter, with a one-line rationale in the config (YAML comment).
  • For each keeper, either fix the findings inline if mechanical, or open a sub-issue if the change is non-trivial or stylistic enough to warrant deliberate review.
  • Update .golangci.yml to linters.default: all with a linters.disable list and any per-linter settings the keepers need.
  • Re-run scripts/invoke-linter and confirm zero findings.

Out of scope:

  • Changing errcheck's exclude-functions list for the Fprint* family (set by the print-strip project).
  • Re-introducing the _, _ = fmt.Fprint* pattern.

Baseline finding counts from linters.default: all

For context — counts are per-linter from a single run; many hit the 50-per-linter cap so actual totals are higher:

Linter Count Linter Count Linter Count
cyclop 50 err113 50 exhaustruct 50
funlen 46 gochecknoglobals 27 gocognit 37
goconst 50 gosec 16 lll 50
mnd 34 nestif 33 paralleltest 50
revive 31 testpackage 25 tparallel 50
varnamelen 50 wrapcheck 50 wsl 50
depguard 50 dupl 19 wsl_v5 16
nlreturn 9 nilerr 12 gocritic 8
nonamedreturns 8 exhaustive 7 unparam 5
staticcheck 5 errorlint 4 dupword 4
ireturn 4 dogsled 3 forbidigo 3
funcorder 3 godot 3 intrange 3
noinlineerr 3 perfsprint 3 nilnil 2
forcetypeassert 2 goprintffuncname 2 noctx 2
usetesting 2 embeddedstructfieldcheck 1 makezero 1
modernize 1 wastedassign 1 whitespace 1

Process suggestion

Group linters into three buckets and walk them:

  1. Style/format (wsl, lll, varnamelen, nlreturn, godot, whitespace, dupword) — high-volume stylistic choices. Each is a one-shot decision: do we want this style enforced in the codebase? If yes, the fix is mechanical; if no, disable with rationale.
  2. Code quality (cyclop, funlen, gocognit, nestif, dupl, goconst, mnd) — complexity thresholds. Decide thresholds the team is comfortable with, configure, then either refactor or disable on a file-by-file basis with //nolint for legitimate hot spots.
  3. Correctness/safety (gosec, errorlint, wrapcheck, err113, nilerr, nilnil, noctx, exhaustive, makezero, wastedassign, forcetypeassert, etc.) — these catch real bugs. Strong bias toward keeping these and fixing the findings.

Acceptance Criteria

  • .golangci.yml declares linters.default: all with a linters.disable list whose entries each carry a one-line YAML comment explaining the decision.
  • golangci-lint run ./... reports zero issues.
  • Any non-trivial fixes that came out of this work are tracked as their own sub-issues or PRs.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions