← Files GophersARCHIVED FILE

skills/go-linting/references/nolint-directives.md

3.87 KB · Oct 5, 2026 · 18:31 UTC

↓ Download file

# //nolint Directives

`//nolint` exists for the cases where the linter is wrong or the right fix is out of scope. Every use of it is a small bet that the suppression will outlive the reason. `nolintlint` enforces the format; this reference covers the *judgment* part.

## The format

```go
//nolint:linter1,linter2 // reason that explains why fixing is wrong
expression()
```

Rules:

- Always name the linter. Bare `//nolint` is forbidden by `nolintlint`.
- Always include a reason after `//`. "Intentional" is not a reason.
- One directive per line of code, attached to that line.

## Scopes

| Scope | How to write it | Use when |
|---|---|---|
| Single line | `code // nolint:errcheck // reason` | Default. Narrowest blast radius. |
| Block / construct | `//nolint:errcheck // reason` on its own line, immediately above the construct | The construct spans multiple lines and the finding applies to all of them. |
| Function | `//nolint:gocyclo // legacy parser; refactor tracked in #1234` directly before the `func` keyword | The whole function is exempt; rare. |
| File | `//nolint:all` at the top of the file | Almost never. Use only for generated code that you cannot regenerate cleanly. |

For generated files, prefer `//go:build` exclusion or the `exclusions.paths` config in `.golangci.yml` over file-scope suppressions.

## Good and bad reasons

```go
// Good — concrete, names the trade-off
//nolint:errcheck // Sync on shutdown can return EAGAIN; nothing to do with it.
_ = logger.Sync()

// Good — points to an issue
//nolint:gocyclo // legacy parser; refactor tracked in #1234
func parseLegacy(...) { ... }

// Bad — circular
//nolint:errcheck // ignored intentionally
_ = something()

// Bad — lies
//nolint:gosec // false positive
cmd := exec.Command("sh", "-c", userInput) // it's not a false positive
```

A reason should answer "why is the linter wrong, *here*?" or "why is the right fix not happening today?".

## Patterns by linter

| Linter | Common legitimate reason |
|---|---|
| `errcheck` | Fire-and-forget on shutdown (`logger.Sync`, `Close` on a discarded body). |
| `gosec` `G404` | Use of `math/rand` for non-security-sensitive randomness (jitter, sampling). |
| `gosec` `G115` | Integer conversion that is provably safe from upstream invariants. |
| `gocyclo` | Hand-written state machines and parsers where complexity is essential. |
| `wrapcheck` | Returning an error from a function in the same package without wrapping. |
| `paralleltest` | Tests that mutate process-wide state (`os.Setenv`, `flag.CommandLine`). |
| `lll` | Long URLs in comments. |

## Anti-patterns

| Anti-pattern | Why it's bad |
|---|---|
| `//nolint` with no linter name | Disables every check on that line. `nolintlint` flags it. |
| `//nolint:all // ` at the top of every file | The linter is now decorative. |
| `//nolint:errcheck` on a security-sensitive call | A missing error check is the bug; the linter found it. |
| `//nolint:gosec // false positive` with no explanation | Reviewers cannot verify the claim. |
| Stale suppressions | Code changes underneath the directive; the reason no longer applies. Audit periodically. |

## Auditing existing suppressions

A useful periodic chore: run `nolintlint` with `allow-unused: false`. It flags suppressions that no longer apply (the underlying finding is gone). Delete those.

For "rotting reasons" (the code changed but the directive stayed), grep for `//nolint:` and re-read each one. If the reason no longer makes sense, fix the code or rewrite the directive.

## File-level alternatives

If you find yourself adding the same suppression in many files, push it into `.golangci.yml` once:

```yaml
linters:
  exclusions:
    rules:
      - path: _test\.go
        linters:
          - errcheck
          - gosec
      - path: cmd/legacy/
        linters:
          - gocyclo
          - funlen
```

This is reviewable, auditable, and survives refactors better than scattered `//nolint`.

SHA-256: 7602513b0da778af28e74c9150b15cfc421e1295b830c184bba95247e9a96899