Propagate cancellation by passing a context.Context to goroutines and checking ctx.Err() or using ctx.Done() to exit early. Use context.WithCancel or context.WithTimeout to create cancellable contexts and pass them to functions that need to stop.
ctx, cancel := context.WithCancel(context.Background())
// Start a goroutine that listens for cancellation
go func() {
select {
case <-ctx.Done():
fmt.Println("Cancelled:", ctx.Err())
return
case <-time.After(5 * time.Second):
fmt.Println("Task completed")
}
}()
// Cancel the context after 2 seconds
time.Sleep(2 * time.Second)
cancel()
// Wait for goroutine to finish
time.Sleep(1 * time.Second)
For groups of goroutines, use errgroup.WithContext to automatically cancel all tasks when one fails or the context is cancelled:
g, ctx := errgroup.WithContext(context.Background())
for i := 0; i < 5; i++ {
i := i
g.Go(func() error {
select {
case <-ctx.Done():
return ctx.Err()
default:
// Do work
return nil
}
})
}
if err := g.Wait(); err != nil {
fmt.Println("Error:", err)
}