TRT
Sign in
easyCoredesign

How does `select` work inside the Go runtime (`pollorder` and `lockorder`), how does `context.Context` propagate cancellation across goroutines in $O(1)$, and.

Explain `selectgo`'s random poll permutation and address-sorted locking, `close(done)` broadcast semantics, and `errgroup.WithContext` scoping.

TRT practice prompt — not a verified question from a named employer.

The Runtime Theory Team2 min read

A strong answer

Three mechanics govern production multiplexing and cancellation in Go: (1) select Runtime Execution (runtime.selectgo): First, selectgo generates a pseudo-random permutation (pollorder) of all cases so no channel can starve another when multiple channels are ready simultaneously; second, it sorts all involved channel addresses (lockorder) to acquire their hchan.lock mutexes without AB/BA deadlock! (2) Timer Reuse (time.NewTimer vs time.After): Calling time.After(d) allocates a new time.Timer channel on the runtime heap on every single loop iteration (Prior to Go 1.23, unstopped timers were not even GC'd until their 5-minute deadline expired, and even in Go 1.23+ allocating 50,000 Timer structs/sec churns the heap!). Always allocate timer := time.NewTimer(d) once outside the loop and call timer.Reset(d)! (3) Context Trees & errgroup (golang.org/x/sync/errgroup): ctx, cancel := context.WithTimeout(parentCtx, 2*time.Second) links a child node into the parent's cancellation tree; calling cancel() closes ctx.Done() (chan struct{}), broadcasting an immediate wakeup to every <-ctx.Done() listener! errgroup.WithContext(ctx) combines WaitGroup, error propagation, ctx cancellation on first error, and bounded concurrency (g.SetLimit(10)) in one primitive.

Closing a ctx.Done() channel wakes all goroutines blocked on <-ctx.Done() simultaneously in O(1) broadcast semantics; inside errgroup.WithContext(ctx), the first goroutine returning a non-nil error cancels the derived ctx and g.Wait() waits for all sibling goroutines to exit before returning that error. Because receiving from a closed channel (<-ctx.Done()) returns immediately without consuming a token, a single close(c.done) inside context.cancelCtx unblocks an arbitrary number $N$ of waiting goroutines concurrently.

Replacing time.After inside a 50k msg/sec loop with a single reusable time.NewTimer + .Reset() reduces timer heap allocations from 50,000/sec down to 1, eliminating megabytes of GC churn per second. In production systems (Go runtime/select.go (selectgo), context package (WithCancel, WithTimeout, WithoutCancel, AfterFunc), and golang.org/x/sync/errgroup (SetLimit, WithContext).), engineers monitor these exact trade-offs to keep p99 latency predictable and prevent resource exhaustion under peak load.

What the interviewer is listening for

  • Traces how select multiplexing, context.Context cancellation trees, and errgroup.Group operates in memory step by step rather than giving a vague textbook definition.
  • States the core correctness invariant and explains why edge cases do not violate it.
  • Quantifies time, space, and hardware costs (close(ctx.Done()) Broadcast, time.After(d) Inside Hot Loop) with concrete numbers.
  • Identifies real-world failure modes (Shadowing ctx with g, ctx := errgroup.WithContext(ctx) and reusing ctx after g.Wait() returns!) and explains how production systems mitigate them.

Common mistakes

  • Treating select multiplexing, context.Context cancellation trees, and errgroup.Group as a black box without explaining the underlying memory or state transitions.
  • Ignoring worst-case tail latency or memory overhead (Forgetting defer cancel() after ctx, cancel := context.WithTimeout(parent, 5*time.Second)).
  • Forgetting boundary conditions and error recovery (Putting case <-time.After(timeout): inside a high-throughput for { select { ... } } loop).

This answer walks

Practice follow-ups

  1. 01What is the subtle bug if you write `g, ctx := errgroup.WithContext(ctx)` (shadowing the outer `ctx` variable!) and then use `ctx` for another DB query *after* `g.Wait()` succeeds?
  2. 02Why must you ALWAYS call the `cancel()` function returned by `context.WithTimeout(parent, 5*time.Second)` (`defer cancel()`) even when your operation finishes in 2 milliseconds?

Not started

Sign in to save your learning progress.

Sign in to save