Go Code Review
Review Workflow
Follow this sequence to avoid false positives and catch version-specific issues:
- Check
go.mod — Note the Go version. This determines which patterns apply (loop variable capture is only an issue pre-1.22, slog is available from 1.21, errors.Join from 1.20). Skip version-gated checks that don't apply.
- Scan changed files — Read full functions, not just diffs. Many Go bugs hide in what surrounds the change.
- Check each category — Work through the checklist below, loading references as needed.
- Verify before reporting — Load beagle-go:review-verification-protocol before submitting findings.
Output Format
Report findings as:
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.
Quick Reference
| Issue Type |
Reference |
| Missing error checks, wrapping, errors.Join |
references/error-handling.md |
| Race conditions, channel misuse, goroutine lifecycle |
references/concurrency.md |
| Interface pollution, naming, generics |
references/interfaces.md |
| Resource leaks, defer misuse, slog, naming |
references/common-mistakes.md |
Review Checklist
Error Handling
Concurrency
Interfaces and Types
Resources and Lifecycle
Naming and Style
Severity Calibration
Critical (Block Merge)
- Unchecked errors on I/O, network, or database operations
- Goroutine leaks (no shutdown path)
- Race conditions on shared state (concurrent map access without sync)
- Unbounded resource accumulation (defer in loop, unclosed connections)
Major (Should Fix)
- Errors returned without context (bare
return err)
- Missing WaitGroup for spawned goroutines
panic for recoverable errors
- Context not propagated to downstream calls
Minor (Consider Fixing)
interface{} instead of any in Go 1.18+ codebases
- Missing doc comments on exports
- Stuttering names
- Slice not preallocated when size is known
Informational (Note Only)
- Suggestions to add generics where code generation exists
- Refactoring ideas for interface design
- Performance optimizations without measured impact
When to Load References
- Reviewing error return patterns → error-handling.md
- Reviewing goroutines, channels, or sync types → concurrency.md
- Reviewing type definitions, interfaces, or generics → interfaces.md
- General review (resources, naming, init, performance) → common-mistakes.md
Valid Patterns (Do NOT Flag)
These are acceptable Go patterns — reporting them wastes developer time:
_ = err with reason comment — Intentionally ignored errors with explanation
- Empty interface /
any — For truly generic code or interop with untyped APIs
- Naked returns in short functions — Acceptable in functions < 5 lines with named returns
- Channel without close — When consumer stops via context cancellation, not channel close
- Mutex protecting struct fields — Even if accessed only via methods, this is correct encapsulation
//nolint directives with reason — Acceptable when accompanied by explanation
- Defer in loop — When function scope cleanup is intentional (e.g., processing files in batches)
- Functional options pattern —
type Option func(*T) with With* constructors is idiomatic
sync.Pool for hot paths — Acceptable for reducing allocation pressure in performance-critical code
context.Background() in main/tests — Valid root context for top-level calls
select with default — Non-blocking channel operation, intentional pattern
- Short variable names in small scope —
i, err, ctx, ok are idiomatic Go
Context-Sensitive Rules
Only flag these issues when the specific conditions apply:
| Issue |
Flag ONLY IF |
| Missing error check |
Error return is actionable (can retry, log, or propagate) |
| Goroutine leak |
No context cancellation path exists for the goroutine |
| Missing defer |
Resource isn't explicitly closed before next acquisition or return |
| Interface pollution |
Interface has > 1 method AND only one consumer exists |
| Loop variable capture |
go.mod specifies Go < 1.22 |
| Missing slog |
go.mod specifies Go >= 1.21 AND code uses log package for structured output |
Before Submitting Findings
Load and follow review-verification-protocol before reporting any issue.
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: go-code-review-23description: Reviews Go code for idiomatic patterns, error handling, concurrency safety, and common mistakes. Use when reviewing .go files, checking error handling, goroutine usage, or interface design. Covers generics (Go 1.18+), errors.Join and slog (Go 1.21+), and Go 1.22 loop variable semantics. Use when this capability is needed.4---56# Go Code Review78## Review Workflow910Follow this sequence to avoid false positives and catch version-specific issues:11121. **Check `go.mod`** — Note the Go version. This determines which patterns apply (loop variable capture is only an issue pre-1.22, `slog` is available from 1.21, `errors.Join` from 1.20). Skip version-gated checks that don't apply.132. **Scan changed files** — Read full functions, not just diffs. Many Go bugs hide in what surrounds the change.143. **Check each category** — Work through the checklist below, loading references as needed.154. **Verify before reporting** — Load beagle-go:review-verification-protocol before submitting findings.1617## Output Format1819Report findings as:2021```text22[FILE:LINE] ISSUE_TITLE23Severity: Critical | Major | Minor | Informational24Description of the issue and why it matters.25```2627## Quick Reference2829| Issue Type | Reference |30|------------|-----------|31| Missing error checks, wrapping, errors.Join | [references/error-handling.md](references/error-handling.md) |32| Race conditions, channel misuse, goroutine lifecycle | [references/concurrency.md](references/concurrency.md) |33| Interface pollution, naming, generics | [references/interfaces.md](references/interfaces.md) |34| Resource leaks, defer misuse, slog, naming | [references/common-mistakes.md](references/common-mistakes.md) |3536## Review Checklist3738### Error Handling39- [ ] All errors checked (no `_ = err` without justifying comment)40- [ ] Errors wrapped with context (`fmt.Errorf("...: %w", err)`)41- [ ] `errors.Is`/`errors.As` used instead of string matching42- [ ] `errors.Join` used for aggregating multiple errors (Go 1.20+)43- [ ] Zero values returned alongside errors4445### Concurrency46- [ ] No goroutine leaks (context cancellation or shutdown signal exists)47- [ ] Channels closed by sender only, exactly once48- [ ] Shared state protected by mutex or sync types49- [ ] WaitGroups used to wait for goroutine completion50- [ ] Context propagated through call chain51- [ ] Loop variable capture handled (pre-Go 1.22 codebases only)5253### Interfaces and Types54- [ ] Interfaces defined by consumers, not producers55- [ ] Interface names follow `-er` convention56- [ ] Interfaces minimal (1-3 methods)57- [ ] Concrete types returned from constructors58- [ ] `any` preferred over `interface{}` (Go 1.18+)59- [ ] Generics used where appropriate instead of `any` or code generation6061### Resources and Lifecycle62- [ ] Resources closed with `defer` immediately after creation63- [ ] HTTP response bodies always closed64- [ ] No `defer` in loops without closure wrapping65- [ ] `init()` functions avoided in favor of explicit initialization6667### Naming and Style68- [ ] Exported names have doc comments69- [ ] No stuttering names (`user.UserService` → `user.Service`)70- [ ] No naked returns in functions > 5 lines71- [ ] Context passed as first parameter72- [ ] `slog` used over `log` for structured logging (Go 1.21+)7374## Severity Calibration7576### Critical (Block Merge)77- Unchecked errors on I/O, network, or database operations78- Goroutine leaks (no shutdown path)79- Race conditions on shared state (concurrent map access without sync)80- Unbounded resource accumulation (defer in loop, unclosed connections)8182### Major (Should Fix)83- Errors returned without context (bare `return err`)84- Missing WaitGroup for spawned goroutines85- `panic` for recoverable errors86- Context not propagated to downstream calls8788### Minor (Consider Fixing)89- `interface{}` instead of `any` in Go 1.18+ codebases90- Missing doc comments on exports91- Stuttering names92- Slice not preallocated when size is known9394### Informational (Note Only)95- Suggestions to add generics where code generation exists96- Refactoring ideas for interface design97- Performance optimizations without measured impact9899## When to Load References100101- Reviewing error return patterns → error-handling.md102- Reviewing goroutines, channels, or sync types → concurrency.md103- Reviewing type definitions, interfaces, or generics → interfaces.md104- General review (resources, naming, init, performance) → common-mistakes.md105106## Valid Patterns (Do NOT Flag)107108These are acceptable Go patterns — reporting them wastes developer time:109110- **`_ = err` with reason comment** — Intentionally ignored errors with explanation111- **Empty interface / `any`** — For truly generic code or interop with untyped APIs112- **Naked returns in short functions** — Acceptable in functions < 5 lines with named returns113- **Channel without close** — When consumer stops via context cancellation, not channel close114- **Mutex protecting struct fields** — Even if accessed only via methods, this is correct encapsulation115- **`//nolint` directives with reason** — Acceptable when accompanied by explanation116- **Defer in loop** — When function scope cleanup is intentional (e.g., processing files in batches)117- **Functional options pattern** — `type Option func(*T)` with `With*` constructors is idiomatic118- **`sync.Pool` for hot paths** — Acceptable for reducing allocation pressure in performance-critical code119- **`context.Background()` in main/tests** — Valid root context for top-level calls120- **`select` with `default`** — Non-blocking channel operation, intentional pattern121- **Short variable names in small scope** — `i`, `err`, `ctx`, `ok` are idiomatic Go122123## Context-Sensitive Rules124125Only flag these issues when the specific conditions apply:126127| Issue | Flag ONLY IF |128|-------|--------------|129| Missing error check | Error return is actionable (can retry, log, or propagate) |130| Goroutine leak | No context cancellation path exists for the goroutine |131| Missing defer | Resource isn't explicitly closed before next acquisition or return |132| Interface pollution | Interface has > 1 method AND only one consumer exists |133| Loop variable capture | `go.mod` specifies Go < 1.22 |134| Missing slog | `go.mod` specifies Go >= 1.21 AND code uses `log` package for structured output |135136## Before Submitting Findings137138Load and follow [review-verification-protocol](../review-verification-protocol/SKILL.md) before reporting any issue.139140---141> Converted and distributed by [TomeVault](https://tomevault.io/claim/existential-birds) — claim your Tome and manage your conversions.142<!-- tomevault:4.0:skill_md:2026-04-11 -->