Concurrency · 3 MIN READ

Cancellation is a request; joining proves exit

Design a worker so it can stop waiting and its owner can wait for it to finish.

Starting a goroutine creates an obligation: identify who asks it to stop and who observes that it has stopped. Canceling a context closes a signal; it does not terminate arbitrary Go code. Every blocking point must cooperate or have another bounded exit.

01

A blocked send needs an escape

A producer may outlive its consumer. If the consumer returns early, an unconditional send can wait forever and keep its goroutine and reachable objects alive. Select between sending and cancellation.

go
func send(ctx context.Context, out chan<- Item, item Item) error {
    select {
    case out <- item:
        return nil
    case <-ctx.Done():
        return ctx.Err()
    }
}
Read the code

If the send and cancellation are both ready, select may choose either. Design the protocol to tolerate that race in intent; cancellation does not mean no operation can ever finish afterwards.

02

Wait for the owned goroutine

A done channel acknowledges exit. The owner cancels, then waits. The worker must observe ctx, including inside downstream operations, or this wait can still block. Production shutdown also needs an overall timeout and a clear policy when a dependency refuses to return.

go
ctx, cancel := context.WithCancel(parent)
done := make(chan struct{})
go func() {
    defer close(done)
    runWorker(ctx) // Must cooperate with cancellation.
}()
// Later, in the owner:
cancel()
<-done
Read the code

The worker closes done because it owns the completion signal. Do not close a work channel from an unrelated receiver while senders may still use it.

03

Use a lifecycle checklist

For every worker, list start, inputs, outputs, stop signal and join point. Include error paths, not only success. Context does not interrupt a mutex lock or CPU loop automatically; choose primitives and loop checkpoints accordingly. A finalizer or the garbage collector is not a goroutine cleanup strategy.

TAKE THIS WITH YOU

Cancellation communicates intent. A join or completion acknowledgement establishes that the owned work has actually stopped.

Check your understanding

Which statement is correct about cancellation and joining?

Go to the source

Progress stays in this browser. No account needed.