Go Code Review
by @anderskev
Reviews Go code for idiomatic patterns, error handling, concurrency safety, and common mistakes. Use when reviewing .go files, checking error handling, gorou...
clawhub install go-code-reviewπ About This Skill
name: go-code-review description: 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.
Go Code Review
Review Workflow
Follow this sequence in order. Do not emit findings until every Pass below is satisfied.
1. Baseline go.mod β Open go.mod and read the go directive.
Pass: You can state the exact go X.YY value (in the review preamble or working notes). Apply version-gated advice only when it matches this baseline (loop capture pre-1.22, slog/structured logging from 1.21, errors.Join from 1.20).
2. Read surrounding code β For each changed .go file, read full functions or logical units that contain the edits, not only the diff hunk.
Pass: At least one full enclosing function (or package-level init/var block) containing the change was read per changed file.
3. Scope the checklist β Decide which Review Checklist blocks apply (error handling, concurrency, interfaces/types, resources, naming). Load references for those blocks; skip blocks that are irrelevant to the diff. Pass: The review (or working notes) lists which checklist blocks you applied, or marks blocks N/A with a one-line reason tied to the diff (e.g. βno concurrency in changeβ).
4. Pre-report verification β Load and follow review-verification-protocol. Pass: The protocolβs Pre-Report Verification Checklist is satisfied for each finding you will report (actual code read, surrounding context checked, βwrongβ vs βdifferent styleβ distinguished, etc.).
Hard gates (same sequence, shorter)
| Step | Objective pass condition |
| --- | --- |
| 1 | go X.YY from go.mod is recorded before version-specific advice. |
| 2 | Full enclosing context read per changed file, not diff-only. |
| 3 | In-scope checklist blocks listed or N/A with diff-tied reason; references opened as needed. |
| 4 | review-verification-protocol completed for every reported issue. |
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
_ = err without justifying comment)fmt.Errorf("...: %w", err))errors.Is/errors.As used instead of string matchingerrors.Join used for aggregating multiple errors (Go 1.20+)Concurrency
Interfaces and Types
-er conventionany preferred over interface{} (Go 1.18+)any or code generationResources and Lifecycle
defer immediately after creationdefer in loops without closure wrappinginit() functions avoided in favor of explicit initializationNaming and Style
user.UserService β user.Service)slog used over log for structured logging (Go 1.21+)Severity Calibration
Critical (Block Merge)
Major (Should Fix)
return err)panic for recoverable errorsMinor (Consider Fixing)
interface{} instead of any in Go 1.18+ codebasesInformational (Note Only)
When to Load References
Valid Patterns (Do NOT Flag)
These are acceptable Go patterns β reporting them wastes developer time:
_ = err with reason comment β Intentionally ignored errors with explanationany β For truly generic code or interop with untyped APIs//nolint directives with reason β Acceptable when accompanied by explanationtype Option func(*T) with With* constructors is idiomaticsync.Pool for hot paths β Acceptable for reducing allocation pressure in performance-critical codecontext.Background() in main/tests β Valid root context for top-level callsselect with default β Non-blocking channel operation, intentional patterni, err, ctx, ok are idiomatic GoContext-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
Satisfy step 4 in Review Workflow: load review-verification-protocol and complete its pre-report checks for each issue.