95 lines | 4.6 KB

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 (or go fmt) on all code; it is the canonical format, not a preference. If a layout looks wrong after gofmt, 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 or SCREAMING_CASE. An unexported constant is maxLength, not MAX_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, not chubby.NewChubby.
  • No Get prefix on getters. The getter for field owner is Owner(); the setter is SetOwner().
  • One-method interfaces take an -er suffix: Reader, Writer, Formatter. Match canonical method signatures (Read, Write, Close, String) when your type does the same job.
  • Initialisms keep a consistent case: ServeHTTP (not ServeHttp), appID (not appId), URL, xmlHTTPRequest.
  • Keep variable names short; closer to their declaration, the shorter they can be. Prefer i to sliceIndex, c to lineCount.

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 panic for normal error handling; use error and multiple return values.
  • Avoid in-band error values like -1, nil, or "". Return an extra error or ok bool instead (the comma-ok idiom).
  • Keep the happy path at minimal indentation: check the error, return early, and let the rest flow down the page. Omit the else after a terminating if.

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; select to multiplex; make to create channels, slices, and maps.
  • Pass context.Context as 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 (c for Client), consistent across all methods. Never me, this, or self.
  • 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.
  • defer cleanup (e.g. f.Close()) right after acquiring the resource; deferred calls run LIFO.
  • new(T) returns a zeroed *T; make initializes 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, never math/rand.

Don't

  • Don't reformat against gofmt or 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 panic as control flow.