Middle · Concurrency

Cancellation is not joining

Does calling cancel guarantee a goroutine has stopped?

Try explaining this aloud before opening the answer. State your assumptions and trace a boundary case.

EXAMPLE · FRAGMENT UNLESS A COMPLETE PROGRAM IS SHOWN

go
select {
case out <- result:
case <-ctx.Done():
    return ctx.Err()
}
Reveal a strong answer
  1. A context signals cancellation and carries deadlines; it does not forcibly terminate goroutines. A function must observe it and propagate it into context-aware I/O.

  2. Join workers explicitly with a WaitGroup, errgroup or a completion channel. Code still needs cleanup after cancellation, and its cleanup must have a bounded, appropriate context.

  3. Make every potentially blocking point cancellable, including acquiring capacity and sending results. A context value should hold request-scoped metadata, not become a dependency container.

Common trap

Launching a goroutine to abandon an uncancellable operation can merely move the leak.

Try it

A producer blocks at out <- result after the caller returns. Repair that send.

Worked solution

Select between sending the result and ctx.Done. Ensure the receiver also joins workers and that the underlying work observes cancellation. A select is not a promise of strict priority if both cases are ready.

Change the constraint

Why should cleanup sometimes use a new bounded context instead of an already-cancelled request context?

How did you do?

Self-assessment, not a compiler pass or interview score. Explain the reasoning unaided before marking understood.

Not marked. Progress stays on this browser, separate from course completion.

Primary references

Checked 2026-10-20. Use documentation for your pinned runtime, driver and tool version.