Skip to content

Table of Contents

Month 4 · Week 3 — Exercises (production handler concerns)

Standard-library-only Go packages with table-driven tests. Each exercise isolates one cross-cutting concern of a real HTTP service — validation, pagination, configuration — as pure, testable logic, so go test runs anywhere with no server or environment setup.

How to run

go test ./exercises/month-04/week-3/...
# or one at a time, verbose:
go test -v ./exercises/month-04/week-3/validate

Prompts

  1. validate/ — Implement request validation that collects every field error at once into a FieldErrors map (first-error-per-field wins). Rules for NewUser: Name required + trimmed + ≤ 50 runes, Email parses via net/mail.ParseAddress, Age in 18..130. Add OK() and a sorted Fields() for deterministic output. Concepts: decode-then-validate, 400 vs 422, fail-collect (Day 099).

  2. paginate/ — Implement Parse(url.Values) Page that reads limit/offset and clamps rather than errors: garbage/missing/<1 limit → DefaultLimit, >MaxLimitMaxLimit, negative offset → 0. Then Slice(total) / SliceStrings must be bounds-safe — an offset past the end yields an empty (non-nil) slice, never a panic. Concepts: hostile query params, clamping, bounds-safe slicing (Day 101).

  3. envconfig/ — Implement Load(lookup LookupFunc) (Config, error) that builds a typed Config from an injected env lookup: defaults for PORT/TIMEOUT/ DEBUG, a required non-empty DATABASE_URL, typed parsing (strconv/time.ParseDuration), and all problems accumulated via errors.Join. MapLookup adapts a map for tests. Concepts: os.LookupEnv semantics, fail-fast config, DI (Day 102).

Results

Exercise Focus Tests Status
validate collected field errors, 400 vs 422 go test
paginate clamped params + bounds-safe slicing go test
envconfig typed env config + joined errors go test

Idiom checklist exercised this week: net/mail.ParseAddress over regex, min-clamped slice bounds, os.LookupEnv's (value, ok), errors.Join for fail-fast config, injected dependencies (now, LookupFunc) for pure tests, and table-driven tests with reflect.DeepEqual.

Rate limiting (Day 103) and JWT/RBAC (Day 104) live as runnable programs in examples/month-04/ratelimit and examples/month-04/jwt rather than as exercises here.