A common mistake is to pass a context to an operation but never check whether it has been canceled. In Go, a context carries a cancellation signal across API boundaries; an operation must observe that signal to stop its work. section 8.6 section 8.6.4
Choose how cancellation begins, then make the receiving operation respond:
- Use context.WithCancel when a caller needs to signal shutdown. Call its cancel function when the work should end; a file watcher can then close its file descriptor. section 8.6.2
- Use context.WithTimeout to stop work that is no longer useful after a deadline. Defer the returned cancel function so the context’s retained resources are released when the caller returns. section 8.6.1
- Watch ctx.Done() and return ctx.Err() when it closes. Err distinguishes cancellation from a passed deadline. section 8.6.4
A blocking channel send or receive defeats that response: cancellation cannot interrupt the wait. Put each channel operation in a select with a ctx.Done() case. section 8.6.4
func f(ctx context.Context) error {
// ...
select { #1
case <-ctx.Done():
return ctx.Err()
case ch1 <- struct{}{}:
}
select { #2
case <-ctx.Done():
return ctx.Err()
case v := <-ch2:
// ...
}
}
Both the send and the receive can finish normally or return when the context is done. section 8.6.4
When propagation cancels too much
An HTTP handler starts an asynchronous publication with the request context, then returns the response. The request context is canceled when the response returns, so publication may stop unexpectedly. Passing context.Background() avoids that cancellation but also loses context values, such as a tracing correlation ID. section 9.1
type detach struct { #1
ctx context.Context
}
func (d detach) Deadline() (time.Time, bool) {
return time.Time{}, false
}
func (d detach) Done() <-chan struct{} {
return nil
}
func (d detach) Err() error {
return nil
}
func (d detach) Value(key any) any {
return d.ctx.Value(key) #2
}
When publication must continue and retain the request’s values, this custom context forwards Value but detaches the parent’s deadline and cancellation. Use it only when that separation is intended. section 9.1




