# context.Context Basics — Go Concurrency Patterns

Source: https://www.skillbyai.com/en/go-concurrency/gc-ctx-basics

> WithCancel, WithTimeout and WithDeadline.

## A tree of contexts

A `context.Context` exposes `Done()` (a channel closed when the context is cancelled or times out), `Err()` (nil while active, then `context.Canceled` or `context.DeadlineExceeded`), `Deadline()` and `Value(key)`. Roots come from `context.Background()` (in `main`, tests and initialisation) or `context.TODO()` (a placeholder while refactoring). Derived contexts form a tree: `WithCancel(parent)` returns a child and a `cancel` function, `WithTimeout(parent, d)` cancels after a duration, and `WithDeadline(parent, t)` at a fixed time. Cancelling a parent cancels all its descendants, never the other way round. **Always call the returned cancel function**, usually with `defer cancel()`, to release resources as soon as the work is done; `go vet` warns when a cancel function is lost. Newer additions such as `WithCancelCause`, `AfterFunc` and `WithoutCancel` exist in recent versions (check the docs).

## One signal, the whole call tree

A context carries cancellation, deadlines and request-scoped values from a caller down to every function and goroutine it starts.

![Three ideas: creating contexts, propagating cancellation, and the rules for context values.](assets/figures/go-concurrency/section-5-map.svg) — Figure 5.1: a root context branching into derived contexts.

## A slow operation bounded by a timeout

The function returns as soon as the context is done.

```go
package main

import (
	"context"
	"errors"
	"fmt"
	"time"
)

func slowQuery(ctx context.Context) (string, error) {
	select {
	case <-time.After(2 * time.Second): // simulated slow work
		return "rows", nil
	case <-ctx.Done():
		return "", ctx.Err()
	}
}

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
	defer cancel() // always release the context's resources

	_, err := slowQuery(ctx)
	if errors.Is(err, context.DeadlineExceeded) {
		fmt.Println("query timed out")
	}
}
```

## A recall notice down the supply chain

When a manufacturer issues a recall, every distributor and shop that received the product hears about it. A shop recalling its own stock does not affect the manufacturer. Cancellation flows from parent to children only.

**Quiz:** What does ctx.Err() return after a WithTimeout context expires?

- [ ] context.Canceled
- [x] context.DeadlineExceeded
- [ ] nil
- [ ] An error created by time.After

*Answer:* context.DeadlineExceeded. Explicit cancel() yields context.Canceled; an expired deadline yields context.DeadlineExceeded.
