Skip to content

Table of Contents

Month 3 · Week 3 — Exercises

Practice for the concurrency patterns: worker pools, fan-out/fan-in, pipelines, bounded parallelism, semaphores, and context cancellation. Each folder is its own package with a solution and table-driven tests. Standard library only. Always run under the race detector — pattern bugs (lost sends, double-close, leaked goroutines) hide from a plain go test.

Exercise Concept Day Run tests
semaphore/ counting semaphore from a buffered channel; TryAcquire, AcquireCtx 074 go test -race ./semaphore
boundedmap/ order-preserving bounded parallel map with first-error + context cancel 074–075 go test -race ./boundedmap
taskgroup/ stdlib mini-errgroup: Go/Wait, SetLimit, WithContext 076 go test -race ./taskgroup

How to use

  1. Try it yourself first — rename the solution aside and re-implement from the prompt below.
  2. Run go test -race ./... from this directory.
  3. Compare with the provided solution; log differences in your day note's "Mistakes" section.

Prompts

  • semaphore: implement a counting Semaphore (constructed with New(n), n clamped to ≥ 1) backed by a buffered channel. Methods: Acquire() (blocks), Release() (panics if called without a matching acquire), TryAcquire() bool (never blocks), and AcquireCtx(ctx) error (returns ctx.Err() if the context is done first). A stress test must assert the number of concurrent holders never exceeds n.
  • boundedmap: implement a generic Map[T, R](ctx, inputs, workers, fn) ([]R, error) that applies fn with at most workers goroutines, preserving input order (write by index, no locks). The first fn error, or a cancelled ctx, must stop work promptly and be returned. Derive a child context so the first error cancels the rest; defer cancel() to avoid a leak; the feeder must select on ctx.Done() so it never blocks after workers exit.
  • taskgroup: implement a stdlib Group mirroring x/sync/errgroup: Go(func() error), Wait() error returning the first error, WithContext(ctx) cancelling on first failure (and on Wait), and SetLimit(n) capping concurrency (acquire a slot in Go, release on return). Use sync.Once so only the first error is kept.

Results

Exercise Tests Status
semaphore TestNeverExceedsLimit, TestTryAcquire, TestAcquireCtxCancelled, TestAcquireCtxSucceeds, TestReleaseWithoutAcquirePanics ✅
boundedmap TestMapPreservesOrder, TestMapRunsFnOncePerInput, TestMapReturnsFirstError, TestMapHonoursCancelledContext ✅
taskgroup TestAllSucceed, TestFirstErrorReturnedAndContextCancelled, TestContextCancelledAfterWaitEvenOnSuccess, TestSetLimitBoundsConcurrency, TestWaitReturnsFirstOfManyErrors ✅

Tip: run all of Week 3 at once with go test -race ./....


⬅ Exercises