context.Context carries cancellation, deadlines, and request-scoped values across API boundaries.
Examples
select races real work against ctx.Done().
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
defer cancel()
ch := make(chan string)
go func() {
time.Sleep(200 * time.Millisecond)
ch <- "done"
}()
select {
case res := <-ch:
fmt.Println(res)
case <-ctx.Done():
fmt.Println("timed out:", ctx.Err())
}Output
timed out: context deadline exceededcancel() closes Done() for every derived context too.
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(10 * time.Millisecond)
cancel()
}()
<-ctx.Done()
fmt.Println(ctx.Err())Output
context canceledUse a private key type, never a bare string.
type ctxKey int
const userKey ctxKey = iota
func withUser(ctx context.Context, user string) context.Context {
return context.WithValue(ctx, userKey, user)
}
func userFrom(ctx context.Context) (string, bool) {
u, ok := ctx.Value(userKey).(string)
return u, ok
}
ctx := withUser(context.Background(), "keith")
user, ok := userFrom(ctx)
fmt.Println(user, ok)Output
keith true| Function | Description |
|---|---|
Background() Context ctx := context.Background() | The root. Assign once, pass down as an argument. |
TODO() Context ctx := context.TODO() | Placeholder root for unwired code. |
WithCancel(parent Context) (Context, CancelFunc) ctx, cancel := context.WithCancel(p) | Pair with defer cancel(). |
WithCancelCause(parent Context) (Context, CancelCauseFunc) ctx, cancel := context.WithCancelCause(p) | cancel(err) is readable later via Cause. |
WithDeadline(parent Context, d time.Time) (Context, CancelFunc) ctx, cancel := context.WithDeadline(p, t) | Self-cancels at d. Still defer cancel(). |
WithTimeout(parent Context, d time.Duration) (Context, CancelFunc) ctx, cancel := context.WithTimeout(p, 5*time.Second) | Shorthand for WithDeadline(now + d). |
WithValue(parent Context, key, val any) Context ctx := context.WithValue(p, k, v) | Read back with ctx.Value(key); needs a type assertion. |
WithoutCancel(parent Context) Context bg := context.WithoutCancel(p) | Keeps values, drops the deadline. |
AfterFunc(ctx Context, f func()) (stop func() bool) stop := context.AfterFunc(ctx, cleanup) | f runs in its own goroutine once ctx is done. |
Cause(ctx Context) error err := context.Cause(ctx) | Richer than ctx.Err() with a *Cause variant. |
Related
Rules that matter
- Always
defer cancel(). Uncanceled children leak in the parent's map. - Cancellation flows down, values look up.
- Safe for concurrent use across goroutines.