# select, Timeouts and context — Go (Golang)

Source: https://www.skillbyai.com/en/go/c-select

> Cancel work that takes too long.

## Wait on several operations

`select` waits on several channel operations and proceeds with whichever is ready. Combined with `context.Context`, it implements timeouts and cancellation: a context created with `context.WithTimeout` or `WithCancel` closes its `Done()` channel when it expires or is cancelled, and `ctx.Err()` says why. Pass `ctx` as the first parameter through call chains (HTTP handlers, database calls) so a cancelled request stops all its work.

## A query racing a deadline, run

I ran this with Go 1.27.1 (`go run .` in a module named demo, standard library only). With a 50 ms deadline, a 10 ms query returns rows, but a 200 ms query is abandoned when the context expires, returning context.DeadlineExceeded.

```go
package main

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

func slowQuery(ctx context.Context, d time.Duration) (string, error) {
	select {
	case <-time.After(d):
		return "rows", nil
	case <-ctx.Done(): // cancelled or deadline exceeded
		return "", ctx.Err()
	}
}

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
	defer cancel()
	res, err := slowQuery(ctx, 10*time.Millisecond)
	fmt.Println("fast:", res, err)
	res, err = slowQuery(ctx, 200*time.Millisecond)
	fmt.Println("slow:", res, err, errors.Is(err, context.DeadlineExceeded))
}
```

Output:

```
fast: rows <nil>
slow:  context deadline exceeded true
```

## Always defer cancel()

Calling the cancel function releases the context's resources even when the work finishes early.

**Quiz:** What does ctx.Done() return?

- [ ] A boolean
- [ ] An error value
- [x] A channel that is closed when the context is cancelled or times out
- [ ] The remaining time

*Answer:* A channel that is closed when the context is cancelled or times out. Select on Done to stop work.
