version: "2" run: concurrency: 4 # Timeout for analysis timeout: 5m # Include test files tests: true issues: max-issues-per-linter: 0 # 0 = unlimited (we want ALL issues) max-same-issues: 50 linters: enable: # correctness - govet # built-in checker: copylocks, printf formats, struct tags, unreachable code - staticcheck # extensive static analysis: deprecated APIs, common mistakes, simplifications - unused # unused variables, functions, types - errcheck # unchecked error returns and type assertions - errorlint # correct use of errors.Is/As and %w wrapping (Go 1.13+) - nilerr # returning nil error when err is non-nil - forcetypeassert # type assertions without comma-ok check - copyloopvar # loop variable copy issues (Go 1.22+) - durationcheck # detect time.Duration * time.Duration bugs - reassign # package-level variable reassignment # style - gocritic # opinionated style: unnecessary conversions, range copies, redundant code - revive # naming conventions, exported types, stuttered package names - wsl_v5 # whitespace and blank line rules for readability - whitespace # trailing whitespace, unnecessary blank lines - godot # exported-symbol comments must end with a period - misspell # common English misspellings in identifiers and comments - dupword # duplicate words in comments and strings (the the, is is) - predeclared # shadowing Go built-ins (len, cap, error) - errname # error type/var naming conventions (ErrFoo, FooError) - asciicheck # non-ASCII identifiers (prevents homoglyph/trojan source attacks) # complexity - gocyclo # cyclomatic complexity threshold - nestif # deeply nested if/else chains - funlen # function length limits (lines and statements) - dupl # code duplication detection # performance - perfsprint # faster alternatives to fmt.Sprintf - unconvert # unnecessary type conversions - ineffassign # assignments to variables never read - goconst # repeated literals that should be constants # security & resources - gosec # security scanner: SQL injection, hardcoded credentials, weak crypto, path traversal - bidichk # dangerous bidirectional Unicode sequences (trojan source CVE-2021-42574) - bodyclose # unclosed HTTP response bodies (connection leaks) - noctx # HTTP requests missing context.Context - containedctx # context.Context stored in struct fields instead of passed as parameter - fatcontext # context.WithValue/WithCancel in loops (unbounded context chain, memory leak) - sqlclosecheck # unclosed sql.Rows and sql.Stmt - rowserrcheck # unchecked sql.Rows.Err() after iteration # logging - sloglint # consistent log/slog code style - loggercheck # key-value pair validation for structured loggers (zap, slog, logr) # testing - testifylint # testify best practices - thelper # test helpers missing t.Helper() - usetesting # use t.Setenv/t.TempDir instead of os equivalents in tests - paralleltest # tests and subtests missing t.Parallel() # modernization & meta - modernize # old patterns replaceable with newer Go features - exptostd # replace golang.org/x/exp/ functions with stdlib equivalents - intrange # range over integer instead of C-style loop (Go 1.22+) - usestdlibvars # use stdlib constants instead of hardcoded values - exhaustive # switch statements not covering all enum values - nolintlint # enforces proper //nolint directive usage disable: - lll # line length — handled by gofmt/gofumpt - prealloc # high false-positive rate; enable only after performance profiling - wrapcheck # forces wrapping all external errors — too noisy as a default - err113 # forces package-level sentinel errors — too opinionated, breaks common patterns - mnd # magic number detector — extremely noisy, flags obvious constants like HTTP 200 - iface # interface pollution detector — too opinionated, not mature enough - nakedret # naked returns — overlaps with funlen (short functions make naked returns fine) - noinlineerr # bans `if err := ...; err != nil {}` — this is idiomatic Go - gocognit # cognitive complexity — redundant with gocyclo + nestif - cyclop # cyclomatic complexity — redundant with gocyclo - depguard # import allow/deny lists — requires per-project configuration - goheader # file header enforcement — project-specific policy - importas # import alias enforcement — requires per-project configuration - funcorder # function ordering — too opinionated for a default - godoclint # godoc validation — overlaps with godot and revive - varnamelen # variable name length — too opinionated, Go favors short names - exhaustruct # all struct fields must be set — extremely noisy, breaks zero-value idiom - gochecknoglobals # no global variables — too strict, many valid uses - gochecknoinits # no init() functions — too strict, many valid uses - unparam # unused function parameters — medium false-positive rate with interfaces - makezero # flags make([]T, n) — noisy, often wrong about intent - testpackage # forces _test package — valid but too opinionated as a default - embeddedstructfieldcheck # embedded type placement — minor style, not worth enforcing - iotamixing # iota in mixed const blocks — very rare issue - unqueryvet # SELECT * detection — too niche for a default config - recvcheck # receiver type consistency — overlaps with gocritic - mirror # bytes/strings mirror patterns — very few real hits - protogetter # proto field access via getters — only for protobuf users - spancheck # OpenTelemetry span checks — only for OTel users - zerologlint # zerolog usage — only for zerolog users exclusions: paths: - vendor$ - third_party$ - testutils$ - examples$ settings: dupl: threshold: 100 # lower => stricter (tokens) errcheck: check-type-assertions: true funlen: lines: 120 statements: 80 goconst: min-len: 3 min-occurrences: 4 gocyclo: min-complexity: 13 # strict; lower => stricter nolintlint: require-explanation: true require-specific: true wsl_v5: allow-first-in-block: true allow-whole-block: false branch-max-lines: 2 formatters: # formatters are opt-in: only those listed here run. Others are left commented # with the reason they stay off (a `disable` block is not valid here and makes # `golangci-lint config verify` fail). enable: - gofumpt # superset of gofmt: applies gofmt's rules first, then its own - goimports # import management: adds imports that --fix introduces, drops unused ones # - gofmt # redundant: gofumpt already applies gofmt's rules # - gci # import grouping/ordering — gofumpt already handles standard grouping # - golines # line wrapping — too opinionated, can break readability # - swaggo # swaggo comment formatting — only for swaggo users settings: gofumpt: extra-rules: true exclusions: generated: lax paths: - third_party$ - builtin$ - examples$