Go by Example: Context Cancellation
Go 1.23
Understand Context Cancellation to manage long-running operations. This example demonstrates using the `context` package to propagate cancellation signals across goroutines, ensuring resources are released and work is stopped when it's no longer needed.
Code
package main
import (
"context"
"fmt"
"time"
)
func main() {
// Create a context that is cancellable
// It returns a derived context and a cancel function
ctx, cancel := context.WithCancel(context.Background())
// Launch a goroutine that does work but checks for cancellation
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
// Context was cancelled, clean up and exit
fmt.Println("Worker: received cancel signal, stopping")
fmt.Println("Worker: reason:", ctx.Err())
return
default:
// Simulate work
fmt.Println("Worker: working...")
time.Sleep(500 * time.Millisecond)
}
}
}(ctx)
// Let the worker run for a bit
time.Sleep(2 * time.Second)
fmt.Println("Main: cancelling context")
// Call cancel to signal the worker to stop
cancel()
// Give worker time to print shutdown message
time.Sleep(time.Second)
}Explanation
The context package is the standard way to handle cancellation, deadlines, and request-scoped values in Go. It allows you to signal to a tree of goroutines that they should stop what they are doing and release resources.
When you create a context with WithCancel, WithDeadline, or WithTimeout, you get a Context object and a CancelFunc. Calling the CancelFunc closes the context's Done channel, which acts as a broadcast signal to all goroutines listening to it.
Best practices for Context:
- Pass context as the first argument to functions (usually named ctx)
- Never store contexts in structs; pass them explicitly
- Always call the cancel function (usually via defer) to avoid leaks
Code Breakdown
12
context.Background() is the root of the context tree. WithCancel returns a copy of the parent that can be cancelled.
18
ctx.Done() returns a channel that is closed when the context is cancelled. Reading from a closed channel returns immediately, making this an effective cancellation signal.
36
Calling cancel() closes the Done channel. This notifies the worker goroutine (and any other children of this context) to stop.

