CodeNebula
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