Go⚡Concurrencyintermediate
context.Context
Go · Concurrency · Run with go run
Explanation
The `context` package propagates deadlines, cancellation signals, and request-scoped values across goroutines and API boundaries. `context.WithTimeout` and `context.WithCancel` return a derived context and a cancel function. When the context is cancelled (or times out), all operations using it receive a `ctx.Done()` signal and should clean up and return.
Real-World Scenario
An HTTP handler creates a context with a 5-second deadline: `ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)`. It passes `ctx` to a database query and an external API call. If either takes longer than 5 seconds (or the client disconnects), both are cancelled automatically — no goroutine leaks.
Quick Snippet
snippet.go
func fetchData(ctx context.Context, url string) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err // includes context.DeadlineExceeded or context.Canceled
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
// Caller
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel() // always cancel to release resources
data, err := fetchData(ctx, "https://api.example.com/data")Full Example
context.go
// Compile: go run context.go
// Output:
// fetching with 2s timeout...
// (result or "context deadline exceeded")
package main
import (
"context"
"fmt"
"io"
"net/http"
"time"
)
func fetchData(ctx context.Context, url string) (string, error) {
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return "", err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
return fmt.Sprintf("status=%d bytes=%d", resp.StatusCode, len(body)), nil
}
func main() {
fmt.Println("fetching with 2s timeout...")
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
result, err := fetchData(ctx, "https://httpbin.org/get")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(result)
}
Run command
go run context.go