aboutsummaryrefslogtreecommitdiff
path: root/languages/go/claude/rules/go.md
diff options
context:
space:
mode:
Diffstat (limited to 'languages/go/claude/rules/go.md')
-rw-r--r--languages/go/claude/rules/go.md82
1 files changed, 82 insertions, 0 deletions
diff --git a/languages/go/claude/rules/go.md b/languages/go/claude/rules/go.md
new file mode 100644
index 0000000..5415a6a
--- /dev/null
+++ b/languages/go/claude/rules/go.md
@@ -0,0 +1,82 @@
+# Go Code Rules
+
+Applies to: `**/*.go`
+
+Go-specific style and structure. Pairs with `go-testing.md` for tests and the
+generic `verification.md` / `commits.md` rules. When in doubt, defer to
+[Effective Go](https://go.dev/doc/effective_go) and the
+[Go Code Review Comments](https://go.dev/wiki/CodeReviewComments) wiki.
+
+## Formatting Is Not a Choice
+
+All code is `gofmt`-clean. The bundle's PostToolUse hook runs `gofmt` and `go
+vet` on every edit and blocks on a violation, and the pre-commit hook re-checks
+staged files. Don't hand-format; let the tool decide. Use `goimports` (or your
+editor's organize-imports) to keep the import block grouped and pruned.
+
+## Errors
+
+- Return errors; don't panic across an API boundary. `panic` is for genuinely
+ unrecoverable, programmer-error states (a corrupt invariant), not for control
+ flow or expected failures.
+- Wrap with context as an error travels up: `fmt.Errorf("load config %s: %w",
+ path, err)`. The `%w` verb preserves the chain for `errors.Is` / `errors.As`.
+- Handle every error where it occurs. Don't assign to `_` to silence one unless
+ you can state why it's safe in a comment.
+- Define sentinel errors (`var ErrNotFound = errors.New("not found")`) or typed
+ errors when callers need to branch on the failure; callers match with
+ `errors.Is` / `errors.As`, never on the message string.
+- Check errors before using the other return value — the value is unspecified
+ when `err != nil`.
+
+## Naming and Shape
+
+- Package names are short, lowercase, no underscores or camelCase; the name is
+ part of every call site (`http.Client`, not `httputil.HTTPClient`). Avoid
+ stutter: `chat.Message`, not `chat.ChatMessage`.
+- Exported identifiers carry a doc comment that begins with the identifier
+ name. Unexported helpers earn a comment when the why isn't obvious.
+- Accept interfaces, return concrete types. Keep interfaces small — one or two
+ methods — and define them in the consuming package, not alongside the
+ implementation.
+- Avoid naked returns except in very short functions; named returns that travel
+ more than a few lines hide what's being returned.
+
+## Concurrency
+
+- Pass `context.Context` as the first parameter (`ctx context.Context`) through
+ any call chain that does I/O or can block; honor cancellation. Never store a
+ context in a struct.
+- A goroutine needs a defined lifecycle — know who stops it and how. Don't
+ launch one without a way for it to exit (a closed channel, a cancelled
+ context, a `sync.WaitGroup`).
+- Share memory by communicating (channels) or guard it (`sync.Mutex`); don't do
+ both for the same state. Run concurrent code under `go test -race`.
+
+## Structure
+
+- Keep functions focused. A function that fetches, parses, decodes, and saves
+ is four functions; the test difficulty in `go-testing.md` is the tell.
+- Zero values should be useful where you can manage it (`bytes.Buffer`,
+ `sync.Mutex` need no constructor). When construction must validate, provide a
+ `NewThing` that returns `(*Thing, error)`.
+- Don't add an interface, generic, or abstraction for a single implementation.
+ Add it when the second caller arrives, not in anticipation.
+- `defer` cleanup (`f.Close()`, `mu.Unlock()`) right after acquiring the
+ resource, so the release is visible next to the acquire.
+
+## Dependencies
+
+- Keep `go.mod` tidy: run `go mod tidy` after changing imports, commit the
+ resulting `go.mod` and `go.sum` together.
+- Prefer the standard library. Pull in a dependency when it earns its
+ maintenance and supply-chain cost, not for a function you could write in a
+ few lines.
+
+## What Not to Do
+
+- Don't ignore a returned error to make the line shorter.
+- Don't reach for `interface{}` / `any` when a concrete type or a small
+ generic constraint says what you mean.
+- Don't refactor surrounding code while fixing a bug — keep the diff scoped.
+- Don't add comments restating what the code already says; comment the why.