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