# Go Backend

> 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'.

- Skill: `muxammadmamajonov/go-backend` (Agent Skill)
- Install (CLI): `npx skillmds@latest add muxammadmamajonov/go-backend`
- Raw SKILL.md: https://api.skillmd.com/api/skills/muxammadmamajonov/go-backend/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: muxammadmamajonov (https://skillmd.com/u/muxammadmamajonov)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/muxammadmamajonov/go-backend

---


# Go Backend Development

## When to use
- Writing HTTP APIs, gRPC services, or CLI tools in Go
- Designing package boundaries, interfaces, and dependency injection
- Implementing concurrency with goroutines, channels, and context propagation
- Integrating databases via `pgx`, `sqlc`, or `database/sql`
- Writing table-driven tests and benchmarks
- Profiling CPU/memory with `pprof`

## Workflow

1. **Confirm Go version** — check `go.mod`. Prefer Go 1.21+ (range over func, `slog` logger, `slices`/`maps` stdlib packages).
2. **Establish package layout** before writing code:
   ```
   cmd/server/main.go          # binary entrypoints only
   internal/                   # private packages
     api/                      # HTTP handlers
     service/                  # business logic
     store/                    # data access layer
     domain/                   # pure types, no imports from above
   pkg/                        # reusable packages safe to import externally
   ```
3. **Define interfaces in the consumer package**, not the implementation package. The `store` package defines the `UserRepository` interface; the `postgres` package implements it.
4. **Inject dependencies through constructors** — `func NewUserService(repo UserRepository, log *slog.Logger) *UserService`. No global state.
5. **Propagate `context.Context` as the first argument** to every function that may block: DB calls, HTTP calls, goroutines with timeouts.
6. **Handle errors explicitly** — check every `err != nil`; wrap with `fmt.Errorf("doing X: %w", err)` to preserve the chain.
7. **Write the handler**: parse → validate → call service → serialise. Use `encoding/json` with `json.NewDecoder(r.Body).Decode(&req)` + a size-limited reader.
8. **Write tests**: table-driven with `t.Run`; use `httptest.NewRecorder` for handlers; use `testcontainers-go` for integration DB tests.
9. **Profile if needed**: `go tool pprof` on `/debug/pprof/` endpoints; `go test -bench -benchmem` for hot paths.
10. **Audit** against .claude/checklists/security.md and .claude/checklists/performance.md before deploying.

## Standards

### Error handling
- Never discard errors; `_ = f()` only for documented intentional ignores with a comment.
- Sentinel errors: `var ErrNotFound = errors.New("not found")`.
- Use `errors.Is` / `errors.As` for matching wrapped errors — not string comparison.
- Return descriptive errors from service layer; translate to HTTP status codes in the handler layer only.

### Concurrency
- Always pass context to goroutines so they can be cancelled.
- Use `sync.WaitGroup` or `errgroup.Group` (`golang.org/x/sync`) for fan-out; never fire-and-forget without tracking.
- Mutexes protect shared state; keep critical sections minimal. Prefer channels for ownership transfer.
- Data races are bugs: run `go test -race ./...` in CI.

### Database (`pgx` / `sqlc`)
- Use `pgxpool.Pool` for connection pooling — never `sql.Open` a new conn per request.
- Prefer `sqlc` to generate type-safe query functions from `.sql` files; avoid raw string queries with interpolated user input.
- Wrap multi-step writes in explicit transactions: `pool.BeginTx → defer tx.Rollback → ... → tx.Commit`.
- Set `pool.MaxConns` and query timeouts via context deadline.

### HTTP
- Use the standard `net/http` handler interface; choose a router (chi, Gin, Echo) for middleware chaining and path params.
- Always set `http.Server` timeouts: `ReadTimeout`, `WriteTimeout`, `IdleTimeout`.
- Validate all path/query/body inputs; return 400 before any business logic on bad input.
- Middleware order: logging → recovery → auth → rate-limit → handler.

### Do not
- Do not use `init()` for dependency setup — makes testing and startup order unpredictable.
- Do not use global `http.DefaultServeMux` in production services — create an explicit `http.ServeMux`.
- Do not ignore goroutine leaks — use `goleak` in tests.
- Do not use `interface{}` / `any` where a concrete type or generic can be used.
- Do not hard-code configuration — read from env vars at startup with validation.

## Common mistakes to avoid

| Mistake | Fix |
|---|---|
| Closing `http.Response.Body` before reading it fully | `io.Copy(io.Discard, resp.Body)` then `resp.Body.Close()`, or read fully first. |
| Range loop variable capture in goroutine | Copy the loop var: `v := v` before the goroutine (fixed in Go 1.22+). |
| Mutex copy (passed by value) | Always pass `sync.Mutex` / `sync.RWMutex` by pointer or embed in a struct. |
| Unbounded goroutine creation under load | Use a worker pool with a buffered channel or `semaphore.Weighted`. |
| JSON numbers decoded to `float64` by default | Use `json.Number` or decode into typed structs, not `map[string]interface{}`. |
| Missing `context.WithTimeout` on outbound calls | Every external call must have a deadline; absence causes goroutine leaks on slow deps. |

## Output format

- New package: directory tree + `package doc` comment + public interface definition.
- Handler: function signature, input struct, service call, and error-to-HTTP translation.
- Test file: `TestXxx(t *testing.T)` with table cases, subtests via `t.Run`, and assertion using `testify/assert`.
- Benchmark: `BenchmarkXxx(b *testing.B)` with `b.ResetTimer()` and `b.ReportAllocs()`.

## Related checklists
- .claude/checklists/security.md
- .claude/checklists/performance.md
- .claude/checklists/qa.md

## Related agents
- .claude/agents/core/orchestrator.md
- .claude/agents/engineering/devops-engineer.md

