# Go HTTP service

Go HTTP service. Standard library `net/http` routing, PostgreSQL through `pgx`, queries generated by `sqlc`.

## Commands
- Build: `go build ./...`
- Test: `go test -race ./...`
- Vet: `go vet ./...`
- Lint: `golangci-lint run`
- Format check: `gofmt -l .` prints nothing
- Regenerate queries after editing `db/queries/*.sql`: `sqlc generate`

## Layout
- `cmd/<app>/main.go`: wiring only. Config, logger, server start.
- `internal/http/`: handlers and routes.
- `internal/<domain>/`: domain logic. No `net/http` imports.
- `internal/db/`: generated sqlc code. Files in this directory are not edited by hand.

## Handlers
- Routes are registered with method patterns: `mux.HandleFunc("POST /messages", h.createMessage)`.
- JSON bodies are decoded with `json.NewDecoder(r.Body)` and `DisallowUnknownFields()`.
- Errors are written with `writeError(w, status, code, message)` from `internal/http/errors.go`.
- Handlers get their dependencies from the `Handler` struct. No package-level state.

## Errors and context
- Wrap errors with context: `fmt.Errorf("load account: %w", err)`. Compare them with `errors.Is` and `errors.As`.
- Every function that does I/O takes `ctx context.Context` as its first parameter.
- Request paths do not call `context.Background()`.

## Logging
- `log/slog` with JSON output. Keys are snake_case: `slog.Info("message sent", "message_id", id)`.
- Message bodies and personal data are never logged.

## Tests
- Table-driven tests with one `t.Run` per case.
- Handlers are tested with `httptest.NewRecorder` and fakes for external clients.
- Database tests carry the `//go:build integration` tag and run with `go test -tags integration ./...`.

## Dependencies
- Add a module only when the task requires it, and name it in the PR description.
