Standard library patterns · 3 MIN READ

Every blocking call should take a context

Make a function that waits stop waiting when told to.

A context is how a caller says "stop, I no longer need this". Anything that could block — a network call, a sleep, a channel receive — should take one and should select on ctx.Done() alongside whatever it was waiting for. A function that ignores its context is a function nothing can cancel.

ctx.Err() says which happened: context.Canceled when someone called cancel, context.DeadlineExceeded when the timeout ran out. Returning it directly is usually right — the caller already knows what it asked for.

SEE THE IDEA

Cancellation has to reach the blocking operation

  1. 01

    Caller

    go
    ctx, cancel := context.WithTimeout(...)

    Sets the lifetime

  2. 02

    Wait

    go
    select { case <-ctx.Done(): }

    Observes the signal

  3. 03

    Finish

    go
    return ctx.Err()

    Reports cancellation or deadline

The context carries a cancellation signal; it does not interrupt work automatically.

In practice

Pass context as the first parameter and propagate it to operations that already accept one. Call the returned cancel function to release resources, even if the deadline eventually expires. Keep contexts out of long-lived structs unless an API explicitly requires that lifetime.

Watch out

Do not use context values for optional arguments or general application state. Values are for request-scoped data crossing API boundaries.

Official reference ↗

Work through the exercise

go
package main

import (
	"context"
	"time"
)

// WaitFor returns nil once d has passed, or the context's error
// if the context finishes first. It must not outlive either.
func WaitFor(ctx context.Context, d time.Duration) error {
	time.Sleep(d)
	return nil
}

func main() {}
Try it yourself

Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.

Progress stays in this browser. No account needed.