Idiomatic Go (Effective Go) — Claude Code rules
Write Go the way the standard library does. These rules are style and idiom, per
Effective Go and the official Go Code Review Comments. (For stdlib-first
library choices, see the go-stdlib pack — this pack complements it.)
Formatting
- Run
gofmt(orgo fmt) on all code; it is the canonical format, not a preference. If a layout looks wrong aftergofmt, rearrange the code rather than fight the tool. - Tabs for indentation, not spaces. No line-length limit — if a line feels long, wrap it and indent with an extra tab.
- Control structures (
if,for,switch) take no parentheses. The opening brace stays on the same line as the statement. - Don't write explicit semicolons; the lexer inserts them.
Naming
- Use
MixedCaps/mixedCaps, never underscores orSCREAMING_CASE. An unexported constant ismaxLength, notMAX_LENGTH. - Visibility is by case: an upper-case first letter exports a name, lower-case keeps it package-private.
- Package names are short, lower-case, single words — no underscores, no
mixedCaps. Avoid meaningless names like
util,common,misc,types. Callers qualify with the package, so don't stutter:chubby.New, notchubby.NewChubby. - No
Getprefix on getters. The getter for fieldownerisOwner(); the setter isSetOwner(). - One-method interfaces take an
-ersuffix:Reader,Writer,Formatter. Match canonical method signatures (Read,Write,Close,String) when your type does the same job. - Initialisms keep a consistent case:
ServeHTTP(notServeHttp),appID(notappId),URL,xmlHTTPRequest. - Keep variable names short; closer to their declaration, the shorter they can
be. Prefer
itosliceIndex,ctolineCount.
Errors
- Error strings are not capitalized (unless they start with a proper noun or
acronym) and do not end with punctuation — they're usually printed inside
other context:
fmt.Errorf("something bad"), not"Something bad.". - When feasible, prefix error strings with the operation or package that
generated them (e.g.
"image: unknown format"). - Handle every error — return it, handle it, or (truly exceptionally) panic.
Never discard errors with
_. - Don't
panicfor normal error handling; useerrorand multiple return values. - Avoid in-band error values like
-1,nil, or"". Return an extraerrororok boolinstead (the comma-ok idiom). - Keep the happy path at minimal indentation: check the error,
returnearly, and let the rest flow down the page. Omit theelseafter a terminatingif.
Interfaces
- Keep interfaces small; one- or two-method interfaces are the norm.
- Accept interfaces, return concrete types. Functions take interface params for flexibility; constructors return the concrete struct/pointer.
- Define an interface in the package that uses it, not the implementor. Don't define interfaces before they're used, and don't add them "for mocking" — test through the real implementation's public API.
- Compose with embedding (
type ReadWriter interface { Reader; Writer }).
Concurrency
- "Do not communicate by sharing memory; instead, share memory by communicating." Pass values over channels rather than guarding shared state.
- Use unbuffered channels to synchronize;
selectto multiplex;maketo create channels, slices, and maps. - Pass
context.Contextas the first parameter of functions that need it:func F(ctx context.Context, …). - Prefer synchronous functions (return results directly) over asynchronous ones.
Other idioms
- Receiver names are a 1–2 letter abbreviation of the type (
cforClient), consistent across all methods. Neverme,this, orself. - Use a pointer receiver to mutate, for large structs, or when the struct holds
a
sync.Mutex; value receivers for small immutable types. When in doubt, use a pointer. defercleanup (e.g.f.Close()) right after acquiring the resource; deferred calls run LIFO.new(T)returns a zeroed*T;makeinitializes slices, maps, and channels.- Doc comments are full sentences that begin with the name and end with a
period:
// Encode writes the JSON encoding of req to w. - For keys or secrets use
crypto/rand, nevermath/rand.
Don't
- Don't reformat against
gofmtor hand-tune whitespace. - Don't name results just to enable naked returns — clarity beats a saved line.
- Don't capitalize or punctuate error strings.
- Don't return interfaces where a concrete type will do.
- Don't reach for
panicas control flow.