Go
WithTimeout
Learn time-bounded context with WithTimeout.
WithTimeout
context.WithTimeout(parent, d) creates a context that cancels itself when the duration passes. It prevents endless waits in network requests and database queries:
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
resp, err := http.DefaultClient.Do(req)
// with no response in 2 seconds, err: context deadline exceeded
Why defer cancel is still needed
Even though the context cancels itself when time runs out, if the work finishes early the internal timer stays in memory until it fires. defer cancel() stops the timer right away. To tell whether an error came from the timeout, use errors.Is(err, context.DeadlineExceeded).
Exercise A slow operation
Write yavas(ctx context.Context) error: it waits with select on time.After(100*time.Millisecond) or ctx.Done() and returns ctx.Err() on cancellation. Call it with a 10 ms timeout and print with errors.Is whether the error is DeadlineExceeded.
Show example solution
package main
import (
"context"
"errors"
"fmt"
"time"
)
func yavas(ctx context.Context) error {
select {
case <-time.After(100 * time.Millisecond):
return nil
case <-ctx.Done():
return ctx.Err()
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
defer cancel()
err := yavas(ctx)
fmt.Println(errors.Is(err, context.DeadlineExceeded))
}
Test yourself
-
If the parent ends in 1 second, when is <code>WithTimeout(parent, 5*time.Second)</code> cancelled?
- In 1 second (with the parent)
- In 5 seconds
- In 6 seconds
- Never
Show answer
In 1 second (with the parent) — A child context can't outlive its parent; the effective deadline is the earlier of the two.
-
Timeout error
if errors.Is(err, context.____) {
log.Println("zaman aşımı")
}
Show answer
if errors.Is(err, context.DeadlineExceeded) {
log.Println("zaman aşımı")
}
-
Error and cause
- context.Canceled
- cancel() was called
- context.DeadlineExceeded
- Time ran out
- NewRequestWithContext
- Binds ctx to a request
- defer cancel()
- Stops the timer
Next lesson: WithValue