[teamai] Push 87 resource(s) from XingfenD
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# 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 exclusions
|
||||
- **`linters.enable`** / **`linters.disable`** — which linters are active
|
||||
- **`linters.settings`** — per-linter thresholds and options
|
||||
- **`formatters`** — 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.
|
||||
|
||||
## 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](../assets/.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 `err` is non-nil (common source of silent failures)
|
||||
- **forcetypeassert** — Flags type assertions without the comma-ok check (`v := x.(T)` instead of `v, ok := x.(T)`)
|
||||
- **copyloopvar** — Detects loop variable copy issues (Go 1.22+)
|
||||
- **errorlint** — Enforces correct use of `errors.Is`/`errors.As` and `%w` wrapping (Go 1.13+ error wrapping)
|
||||
- **durationcheck** — Detects `time.Duration * time.Duration` multiplication bugs (e.g., `2 * time.Second * time.Minute` produces 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 with `Err` (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.Itoa` instead of `fmt.Sprintf("%d", n)`)
|
||||
- **unconvert** — Detects unnecessary type conversions (e.g., `int(x)` when `x` is already `int`)
|
||||
- **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.Context` stored in struct fields instead of passed as a parameter (anti-pattern per Go docs)
|
||||
- **fatcontext** — Detects `context.WithValue`/`WithCancel` in loops, creating unbounded context chains that grow each iteration and cause memory leaks
|
||||
- **bodyclose** — Ensures HTTP response bodies are closed (unclosed bodies leak connections)
|
||||
- **sqlclosecheck** — Ensures `sql.Rows` and `sql.Stmt` are closed after use
|
||||
- **rowserrcheck** — Ensures `sql.Rows.Err()` is checked after iteration
|
||||
|
||||
### Logging
|
||||
|
||||
- **sloglint** — Enforces consistent `log/slog` code style: proper key-value pairing, message formatting, and level usage
|
||||
- **loggercheck** — 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 site
|
||||
- **paralleltest** — Detects tests and subtests missing `t.Parallel()` calls
|
||||
- **testifylint** — Enforces testify best practices (e.g., `assert.Equal(t, expected, actual)` over `assert.True(t, expected == actual)`)
|
||||
- **usetesting** — Suggests `t.Setenv`/`t.TempDir` instead of `os.Setenv`/`os.MkdirTemp` in 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`, `cmp` packages added in Go 1.21)
|
||||
- **intrange** — Suggests `range N` over C-style `for i := 0; i < N; i++` loops (Go 1.22+)
|
||||
- **usestdlibvars** — Replaces hardcoded strings/numbers with stdlib constants (e.g., `http.MethodGet` instead of `"GET"`)
|
||||
- **exhaustive** — Ensures switch statements on enum types cover all possible values
|
||||
- **nolintlint** — Enforces proper `//nolint` directive usage: requires linter name and justification comment (configured with `require-explanation` and `require-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
|
||||
@@ -0,0 +1,68 @@
|
||||
# Nolint Directives
|
||||
|
||||
## Syntax
|
||||
|
||||
```go
|
||||
//nolint:lintername // justification explaining why this suppression is needed
|
||||
```
|
||||
|
||||
Place the directive on the same line as the flagged code, or on the line immediately above it.
|
||||
|
||||
## Rules
|
||||
|
||||
1. **MUST specify the linter name** — bare `//nolint` suppresses all linters on that line and makes it impossible to track what is being suppressed
|
||||
2. **MUST add a justification comment** — future readers (and your future self) need to understand why
|
||||
3. **The `nolintlint` linter enforces both rules** — it will flag bare `//nolint` and missing reasons
|
||||
4. **MUST fix the root cause before suppressing** — only suppress after confirming the issue is a false positive or an intentional pattern
|
||||
|
||||
## Examples
|
||||
|
||||
```go
|
||||
// Specific linter with reason
|
||||
//nolint:errcheck // fire-and-forget logging, error not actionable
|
||||
_ = logger.Sync()
|
||||
|
||||
// Type assertion is safe because preceding type switch guarantees the type
|
||||
v := x.(MyType) //nolint:forcetypeassert // guaranteed by type switch on line 42
|
||||
|
||||
// Orchestration function has inherent complexity
|
||||
//nolint:gocyclo // orchestration function coordinating 8 subsystems
|
||||
func orchestrate() error {
|
||||
|
||||
// Table-driven test with many cases
|
||||
//nolint:funlen // table-driven test, length is proportional to case count
|
||||
func TestParser(t *testing.T) {
|
||||
|
||||
// Intentional parallel structure is clearer than abstracting
|
||||
//nolint:dupl // intentional parallel structure for readability
|
||||
```
|
||||
|
||||
## Multiple Linters
|
||||
|
||||
Suppress multiple linters on one line with comma separation:
|
||||
|
||||
```go
|
||||
//nolint:errcheck,gosec // fire-and-forget in test helper
|
||||
```
|
||||
|
||||
## When to Suppress vs. When to Fix
|
||||
|
||||
**Fix** (almost always):
|
||||
|
||||
- `errcheck` — check the error, even if just logging it
|
||||
- `govet` — these are usually real bugs
|
||||
- `staticcheck` — deprecated API usage, logic errors
|
||||
- `bodyclose`, `sqlclosecheck` — resource leaks are real issues
|
||||
|
||||
**Suppress** (with justification):
|
||||
|
||||
- `funlen` — table-driven tests with many cases
|
||||
- `gocyclo` — orchestration functions where splitting would obscure the flow
|
||||
- `dupl` — intentional parallel structure that is clearer than an abstraction
|
||||
- `exhaustive` — when a default case intentionally handles remaining values
|
||||
- `goconst` — when extracting to a constant would reduce clarity (e.g., test assertions)
|
||||
|
||||
**Never suppress without strong justification**:
|
||||
|
||||
- Security linters (`bodyclose`, `sqlclosecheck`, `rowserrcheck`) — these catch real resource leaks
|
||||
- `errcheck` on production code paths — unchecked errors cause silent failures
|
||||
Reference in New Issue
Block a user