---
overlay: Go Specialization
parent_agent: Super Coder
description: "Go idioms, error handling, and concurrency patterns"
---

## GO-SPECIFIC GUIDELINES

You are working in a **Go** codebase. Apply these principles with zero exceptions.

### Error Handling — The Go Way
- **Always check errors:** `if err != nil { return fmt.Errorf("context: %w", err) }`
- Use `%w` for error wrapping (enables `errors.Is()` and `errors.As()`) — not `%v`
- Create sentinel errors with `var ErrNotFound = errors.New("not found")` for expected conditions
- Create custom error types only when callers need to inspect error details
- Never ignore errors — if you truly don't need it, assign to `_` with a comment explaining why
- Return errors, don't panic — `panic` is for unrecoverable programming errors only

### Interfaces — Accept Interfaces, Return Structs
- Define interfaces at the **consumer** site, not the implementation site
- Keep interfaces small — 1-3 methods. Compose larger behaviors from small interfaces
- Use `io.Reader`, `io.Writer`, `fmt.Stringer`, `error` — don't reinvent standard interfaces
- Never export interfaces for concrete types unless multiple implementations exist

### Goroutine Lifecycle
- **Always ensure goroutines can be stopped** — use `context.Context` for cancellation
- Pass `context.Context` as the first parameter to functions that do I/O or may block
- Use `sync.WaitGroup` to wait for goroutine completion
- Use `errgroup.Group` for parallel tasks that can fail
- Never launch a goroutine without a clear shutdown path — leaked goroutines are resource leaks
- Use channels for communication, mutexes for state — prefer channels when both work

### Code Structure
- Follow **standard Go project layout** — respect the existing project conventions
- Exported names (`PascalCase`) are public API — unexported (`camelCase`) are internal
- One package per directory — package name matches directory name (lowercase, no underscores)
- Group imports: stdlib → external → internal (separated by blank lines)
- Use `internal/` for packages that should not be imported outside the module

### Patterns
- Use **functional options** for configurable constructors: `func NewServer(opts ...Option) *Server`
- Use **table-driven tests** as the default test pattern
- Use `struct embedding` for composition — not inheritance
- Use `defer` for cleanup — but understand it runs at function exit, not block exit
- Prefer `strings.Builder` for string concatenation in loops
- Use `context.WithValue` sparingly — prefer explicit parameters

### Naming Conventions
- `PascalCase` for exported, `camelCase` for unexported
- Receivers: short (1-2 letters), consistent within type: `func (s *Server) Start()`
- Acronyms are all-caps: `userID`, `httpClient`, `URL`
- Getters don't use `Get` prefix: `Name()` not `GetName()`
- Package names are lowercase, single word when possible

### Testing Considerations
- Use table-driven tests with `t.Run()` for subtests
- Use `t.Helper()` in test helper functions for better error reporting
- Use `t.Parallel()` when tests are independent
- Prefer `testify/assert` or standard `if got != want` — follow project convention
