1---2name: go-backend3description: Use for Go backend services — net/http, chi/Gin/Echo, goroutine/channel concurrency, context, pgx/sqlc, testing, hardening. Triggers — go.mod, .go files, 'gin', 'chi', 'echo', 'pgx'.4---56# Go Backend Development78## When to use9- Writing HTTP APIs, gRPC services, or CLI tools in Go10- Designing package boundaries, interfaces, and dependency injection11- Implementing concurrency with goroutines, channels, and context propagation12- Integrating databases via `pgx`, `sqlc`, or `database/sql`13- Writing table-driven tests and benchmarks14- Profiling CPU/memory with `pprof`1516## Workflow17181. **Confirm Go version** — check `go.mod`. Prefer Go 1.21+ (range over func, `slog` logger, `slices`/`maps` stdlib packages).192. **Establish package layout** before writing code:20 ```21 cmd/server/main.go # binary entrypoints only22 internal/ # private packages23 api/ # HTTP handlers24 service/ # business logic25 store/ # data access layer26 domain/ # pure types, no imports from above27 pkg/ # reusable packages safe to import externally28 ```293. **Define interfaces in the consumer package**, not the implementation package. The `store` package defines the `UserRepository` interface; the `postgres` package implements it.304. **Inject dependencies through constructors** — `func NewUserService(repo UserRepository, log *slog.Logger) *UserService`. No global state.315. **Propagate `context.Context` as the first argument** to every function that may block: DB calls, HTTP calls, goroutines with timeouts.326. **Handle errors explicitly** — check every `err != nil`; wrap with `fmt.Errorf("doing X: %w", err)` to preserve the chain.337. **Write the handler**: parse → validate → call service → serialise. Use `encoding/json` with `json.NewDecoder(r.Body).Decode(&req)` + a size-limited reader.348. **Write tests**: table-driven with `t.Run`; use `httptest.NewRecorder` for handlers; use `testcontainers-go` for integration DB tests.359. **Profile if needed**: `go tool pprof` on `/debug/pprof/` endpoints; `go test -bench -benchmem` for hot paths.3610. **Audit** against .claude/checklists/security.md and .claude/checklists/performance.md before deploying.3738## Standards3940### Error handling41- Never discard errors; `_ = f()` only for documented intentional ignores with a comment.42- Sentinel errors: `var ErrNotFound = errors.New("not found")`.43- Use `errors.Is` / `errors.As` for matching wrapped errors — not string comparison.44- Return descriptive errors from service layer; translate to HTTP status codes in the handler layer only.4546### Concurrency47- Always pass context to goroutines so they can be cancelled.48- Use `sync.WaitGroup` or `errgroup.Group` (`golang.org/x/sync`) for fan-out; never fire-and-forget without tracking.49- Mutexes protect shared state; keep critical sections minimal. Prefer channels for ownership transfer.50- Data races are bugs: run `go test -race ./...` in CI.5152### Database (`pgx` / `sqlc`)53- Use `pgxpool.Pool` for connection pooling — never `sql.Open` a new conn per request.54- Prefer `sqlc` to generate type-safe query functions from `.sql` files; avoid raw string queries with interpolated user input.55- Wrap multi-step writes in explicit transactions: `pool.BeginTx → defer tx.Rollback → ... → tx.Commit`.56- Set `pool.MaxConns` and query timeouts via context deadline.5758### HTTP59- Use the standard `net/http` handler interface; choose a router (chi, Gin, Echo) for middleware chaining and path params.60- Always set `http.Server` timeouts: `ReadTimeout`, `WriteTimeout`, `IdleTimeout`.61- Validate all path/query/body inputs; return 400 before any business logic on bad input.62- Middleware order: logging → recovery → auth → rate-limit → handler.6364### Do not65- Do not use `init()` for dependency setup — makes testing and startup order unpredictable.66- Do not use global `http.DefaultServeMux` in production services — create an explicit `http.ServeMux`.67- Do not ignore goroutine leaks — use `goleak` in tests.68- Do not use `interface{}` / `any` where a concrete type or generic can be used.69- Do not hard-code configuration — read from env vars at startup with validation.7071## Common mistakes to avoid7273| Mistake | Fix |74|---|---|75| Closing `http.Response.Body` before reading it fully | `io.Copy(io.Discard, resp.Body)` then `resp.Body.Close()`, or read fully first. |76| Range loop variable capture in goroutine | Copy the loop var: `v := v` before the goroutine (fixed in Go 1.22+). |77| Mutex copy (passed by value) | Always pass `sync.Mutex` / `sync.RWMutex` by pointer or embed in a struct. |78| Unbounded goroutine creation under load | Use a worker pool with a buffered channel or `semaphore.Weighted`. |79| JSON numbers decoded to `float64` by default | Use `json.Number` or decode into typed structs, not `map[string]interface{}`. |80| Missing `context.WithTimeout` on outbound calls | Every external call must have a deadline; absence causes goroutine leaks on slow deps. |8182## Output format8384- New package: directory tree + `package doc` comment + public interface definition.85- Handler: function signature, input struct, service call, and error-to-HTTP translation.86- Test file: `TestXxx(t *testing.T)` with table cases, subtests via `t.Run`, and assertion using `testify/assert`.87- Benchmark: `BenchmarkXxx(b *testing.B)` with `b.ResetTimer()` and `b.ReportAllocs()`.8889## Related checklists90- .claude/checklists/security.md91- .claude/checklists/performance.md92- .claude/checklists/qa.md9394## Related agents95- .claude/agents/core/orchestrator.md96- .claude/agents/engineering/devops-engineer.md