Go

Can you implement your own Context type? How does the stdlib propagate cancellation from a custom parent?

Question 284HardGo 1.22 to 1.25

Yes, any type that implements the four methods is a Context, and all methods must be safe for concurrent use. The most common custom context is not written from scratch: it embeds context.Context and overrides one method, for example a context that hides values for sandboxing, or a test double.

// Hides all values but keeps cancellation and deadline.
type noValues struct{ context.Context }

func (noValues) Value(any) any { return nil }

func isolate(ctx context.Context) context.Context { return noValues{ctx} }

When you derive a child from a custom parent, propagateCancel works like this:

  1. It calls parent.Value(&cancelCtxKey) (an unexported key) to find an underlying stdlib *cancelCtx. If found and its Done channel matches the parent's Done(), the child registers there directly. Embedding keeps this fast path. In the example above, overriding Value breaks it, because the lookup now returns nil.
  2. Otherwise, if the parent has an AfterFunc(func()) func() bool method, that method is used.
  3. Otherwise it starts one goroutine per child that waits on parent.Done(). This works, but costs memory and scheduler work at scale.

What the interviewer is looking for: knowing that custom contexts are rarely needed, that wrapping by embedding is the idiom, and the hidden goroutine cost of the fallback path.

More on Context

All 35 Context questions