GO / CHAPTER 13
Cancellation and bounded concurrent work
AdvancedMake workers stop cooperatively and assign channel ownership.
By the end of this chapter
- Observe context cancellation
- Separate cancellation from completion
- Assign channel closing to the sender side
The idea
A context carries a cancellation signal and optionally a deadline through a call chain. Cancellation is cooperative: work stops only when the code or a called operation observes the signal. A worker can select between sending a result and receiving from ctx.Done, preventing an abandoned receiver from trapping it forever. Always define how callers learn whether work completed or was canceled.
Cancellation does not wait for every goroutine to exit. Use an explicit completion mechanism when shared resources must remain available until workers finish. Channel ownership also matters: the sender side should coordinate closing after all sends are finished. Receiving from a closed channel remains valid and reports completion through the second receive result; sending to a closed channel panics. Avoid tests that assume one scheduler ordering when several outcomes are permitted.
package main
import ("fmt"; "context")
func main(){ ctx,cancel:=context.WithCancel(context.Background()); cancel(); <-ctx.Done(); fmt.Println(ctx.Err()==context.Canceled); ch:=make(chan int,1); ch<-7; close(ch); v,ok:=<-ch; fmt.Println(v,ok); _,ok=<-ch; fmt.Println(ok) }true 7 true false
Cancellation closes the Done channel. A closed buffered channel still yields queued data before receives report that no values remain.
Try it yourself
Design a worker send that can exit when the caller cancels instead of blocking forever.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING