Golang Context Package Quiz

Golang
0 Passed
0% acceptance

35 comprehensive questions on Golang's context package, covering context.Background() & TODO(), context cancellation, deadlines & timeouts, passing values, and best practices — with 18 code examples demonstrating proper context usage.

35 Questions
~70 minutes
1

Question 1

What is the context package in Golang?

go
import "context"

ctx := context.Background()
// ctx carries deadlines, cancellation, and values
A
Package for carrying deadlines, cancellation signals, and request-scoped values
B
Package for goroutine management
C
Package for error handling
D
Package for logging
2

Question 2

What is the difference between context.Background() and context.TODO()?

go
func main() {
    ctx := context.Background()  // For main functions, tests
    
    func() {
        ctx := context.TODO()  // When unsure which context to use
    }()
}
A
Background() for root contexts, TODO() as placeholder when context is unclear
B
No difference
C
Background() has timeouts, TODO() doesn't
D
TODO() is deprecated
3

Question 3

How do you implement cancellation with context?

go
ctx, cancel := context.WithCancel(context.Background())

go func() {
    select {
    case <-ctx.Done():
        fmt.Println("Cancelled")
        return
    case <-time.After(5 * time.Second):
        fmt.Println("Work done")
    }
}()

// Later: cancel()
A
Use WithCancel() to create cancellable context, check ctx.Done()
B
Use time.Sleep()
C
Use channels
D
Cannot implement cancellation
4

Question 4

How do you set a deadline with context?

go
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))
defer cancel()

select {
case <-time.After(10 * time.Second):
    fmt.Println("Work done")
case <-ctx.Done():
    fmt.Println("Deadline exceeded")
}
A
Use WithDeadline() to set absolute deadline
B
Use WithTimeout()
C
Use time.Sleep()
D
Cannot set deadlines
5

Question 5

How do you set a timeout with context?

go
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

// ctx will be cancelled after 5 seconds
A
Use WithTimeout() for relative timeouts
B
Use WithDeadline()
C
Use time.Sleep()
D
Cannot set timeouts
6

Question 6

How do you pass values through context?

go
type key string

const userKey key = "user"

ctx := context.WithValue(context.Background(), userKey, "alice")

func getUser(ctx context.Context) string {
    if user, ok := ctx.Value(userKey).(string); ok {
        return user
    }
    return ""
}
A
Use WithValue() to store, Value() to retrieve with type assertion
B
Use global variables
C
Use channels
D
Cannot pass values
7

Question 7

What happens when a context is cancelled?

go
ctx, cancel := context.WithCancel(context.Background())

select {
case <-ctx.Done():
    err := ctx.Err()
    fmt.Println("Error:", err)  // context canceled
}
A
ctx.Done() channel closes, ctx.Err() returns cancellation reason
B
Program panics
C
Nothing happens
D
Goroutines stop automatically
8

Question 8

How do you propagate context through function calls?

go
func handler(ctx context.Context) {
    userID := getUserID(ctx)
    data := fetchData(ctx, userID)
    process(ctx, data)
}

func fetchData(ctx context.Context, userID string) Data {
    req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
    // context flows through HTTP request
}
A
Pass context as first parameter to functions
B
Use global context
C
Use channels
D
Cannot propagate
9

Question 9

What is context inheritance?

go
parentCtx := context.Background()
childCtx, cancel := context.WithTimeout(parentCtx, time.Second)

go func() {
    <-childCtx.Done()
    // child cancelled when parent is cancelled or timeout
}()

// Cancelling parent cancels child too
A
Child contexts inherit cancellation from parent contexts
B
Parent inherits from child
C
No inheritance
D
Circular inheritance
10

Question 10

How do you handle context in HTTP handlers?

go
func handler(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()  // Get request context
    
    select {
    case <-ctx.Done():
        // Client disconnected or timeout
        return
    case result := <-doWork(ctx):
        json.NewEncoder(w).Encode(result)
    }
}
A
Use r.Context() to get request context, check Done() for cancellation
B
Create new context
C
Ignore context
D
Cannot handle in HTTP
11

Question 11

What is the problem with this context usage?

go
func badHandler() {
    ctx := context.Background()
    go longRunningTask(ctx)  // Never cancelled
}

func longRunningTask(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
            // work
        }
    }
}
A
Using Background() context that never cancels, causing goroutine leak
B
Using goroutines
C
Using select
D
No problem
12

Question 12

How do you implement a context-aware worker pool?

go
func workerPool(ctx context.Context, jobs <-chan Job) {
    var wg sync.WaitGroup
    
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for {
                select {
                case job, ok := <-jobs:
                    if !ok {
                        return
                    }
                    processJob(ctx, job)
                case <-ctx.Done():
                    return
                }
            }
        }()
    }
    wg.Wait()
}
A
Check ctx.Done() in worker loop to enable cancellation
B
Use time.Sleep()
C
Use sync.WaitGroup only
D
Cannot implement
13

Question 13

How do you check if a context has a deadline?

go
deadline, ok := ctx.Deadline()
if ok {
    fmt.Printf("Deadline: %v\n", deadline)
} else {
    fmt.Println("No deadline")
}
A
Use Deadline() method which returns time and bool
B
Use Done() channel
C
Use Err() method
D
Cannot check deadline
14

Question 14

What is context.WithValue best practice?

go
type contextKey string

const userIDKey contextKey = "userID"

func WithUserID(ctx context.Context, userID string) context.Context {
    return context.WithValue(ctx, userIDKey, userID)
}

func GetUserID(ctx context.Context) string {
    if id, ok := ctx.Value(userIDKey).(string); ok {
        return id
    }
    return ""
}
A
Use unexported key types and helper functions to avoid collisions
B
Use string keys directly
C
Store complex objects
D
No best practices
15

Question 15

How do you implement cascading cancellation?

go
func parentTask(ctx context.Context) {
    childCtx, cancel := context.WithCancel(ctx)
    defer cancel()
    
    go childTask(childCtx)
    
    select {
    case <-ctx.Done():
        // Parent cancelled, child will be cancelled too
        return
    case <-time.After(time.Second):
        // Work done
    }
}
A
Create child contexts from parent, cancellation cascades down
B
Use separate contexts
C
Use channels
D
Cannot cascade
16

Question 16

What is the context leak problem?

go
func leakyFunction() {
    ctx := context.Background()
    ch := make(chan int)
    
    go func() {
        // This goroutine will run forever
        for {
            select {
            case <-ch:
                return
            default:
                // work that never checks ctx.Done()
            }
        }
    }()
    
    // Forgot to close ch or cancel ctx
}
A
Goroutines that don't respect context cancellation continue running
B
Memory leak
C
Race condition
D
No problem
17

Question 17

How do you implement timeout for database queries?

go
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

rows, err := db.QueryContext(ctx, "SELECT * FROM users")
if err != nil {
    if ctx.Err() == context.DeadlineExceeded {
        // Handle timeout
    }
}
A
Use QueryContext() with timeout context
B
Use time.Sleep()
C
Use channels
D
Cannot timeout DB queries
18

Question 18

What is the context.TODO() usage pattern?

go
func processRequest(req *Request) error {
    // Not sure what context to use yet
    ctx := context.TODO()
    
    // Later, when context is available:
    // ctx = req.Context()
    
    return doWork(ctx)
}
A
Placeholder when context handling is incomplete
B
For production code
C
For tests
D
Deprecated
19

Question 19

How do you handle multiple contexts in a function?

go
func complexOperation(ctx context.Context) error {
    // Create derived contexts for sub-operations
    dbCtx, dbCancel := context.WithTimeout(ctx, 2*time.Second)
    defer dbCancel()
    
    apiCtx, apiCancel := context.WithTimeout(ctx, 5*time.Second)
    defer apiCancel()
    
    // Use appropriate context for each operation
    err := db.QueryContext(dbCtx, "SELECT...")
    if err != nil {
        return err
    }
    
    return callAPI(apiCtx)
}
A
Create derived contexts with appropriate timeouts for different operations
B
Use single context for everything
C
Ignore contexts
D
Cannot handle multiple
20

Question 20

What is the context.Value() lookup behavior?

go
ctx1 := context.WithValue(context.Background(), "key", "value1")
ctx2 := context.WithValue(ctx1, "key", "value2")

fmt.Println(ctx2.Value("key"))  // "value2" (closest)
fmt.Println(ctx1.Value("key"))  // "value1"
A
Value() returns the value from the closest context in the chain
B
Returns all values
C
Returns nil
D
Panics
21

Question 21

How do you implement graceful shutdown with context?

go
func server() {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
    
    go func() {
        s := &http.Server{}
        if err := s.ListenAndServe(); err != nil {
            // handle error
        }
    }()
    
    // Wait for shutdown signal
    <-shutdownSignal
    
    // Cancel context to signal shutdown
    cancel()
    
    // Give server time to shutdown gracefully
    shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer shutdownCancel()
    s.Shutdown(shutdownCtx)
}
A
Use context cancellation to signal shutdown, then use Shutdown() with timeout
B
Use os.Exit()
C
Use panic
D
Cannot shutdown gracefully
22

Question 22

What is the problem with storing pointers in context?

go
type User struct { Name string }

func handler(ctx context.Context) {
    user := &User{Name: "Alice"}
    ctx = context.WithValue(ctx, "user", user)
    
    go func() {
        // user pointer might be invalid if handler returns
        u := ctx.Value("user").(*User)
        fmt.Println(u.Name)
    }()
}
A
Pointers can become invalid if goroutines outlive the data
B
Memory leak
C
Race condition
D
No problem
23

Question 23

How do you implement request tracing with context?

go
type traceIDKey struct{}

func WithTraceID(ctx context.Context, id string) context.Context {
    return context.WithValue(ctx, traceIDKey{}, id)
}

func GetTraceID(ctx context.Context) string {
    if id, ok := ctx.Value(traceIDKey{}).(string); ok {
        return id
    }
    return ""
}

func logWithTrace(ctx context.Context, msg string) {
    traceID := GetTraceID(ctx)
    log.Printf("[%s] %s", traceID, msg)
}
A
Store trace ID in context and retrieve in logging functions
B
Use global variables
C
Use channels
D
Cannot implement tracing
24

Question 24

What is the context tree pattern?

go
func requestHandler(ctx context.Context) {
    // Root context from request
    
    // Database operations get shorter timeout
    dbCtx, dbCancel := context.WithTimeout(ctx, time.Second)
    defer dbCancel()
    
    // External API calls get medium timeout
    apiCtx, apiCancel := context.WithTimeout(ctx, 5*time.Second)
    defer apiCancel()
    
    // Background tasks get cancellable context
    bgCtx, bgCancel := context.WithCancel(ctx)
    defer bgCancel()
    
    // All contexts cancelled when request ctx is cancelled
}
A
Creating derived contexts with different properties for different operations
B
Single context for everything
C
No context tree
D
Circular contexts
25

Question 25

How do you handle context in testing?

go
func TestHandler(t *testing.T) {
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    
    req := httptest.NewRequest("GET", "/", nil).WithContext(ctx)
    
    // Test handler with context
    handler := http.HandlerFunc(myHandler)
    handler.ServeHTTP(httptest.NewRecorder(), req)
    
    // Context should be cancelled by timeout
    select {
    case <-ctx.Done():
        // Expected
    case <-time.After(2 * time.Second):
        t.Error("Context not cancelled")
    }
}
A
Create test contexts with timeouts, use WithContext() for HTTP requests
B
Use context.Background()
C
Ignore context in tests
D
Cannot test context
26

Question 26

What is the context.Value() performance consideration?

A
Value() lookup traverses context chain, can be slow for deep chains
B
Very fast
C
Uses hashing
D
No performance issue
27

Question 27

How do you implement a context-aware ticker?

go
func contextTicker(ctx context.Context, interval time.Duration) <-chan time.Time {
    ch := make(chan time.Time)
    go func() {
        defer close(ch)
        ticker := time.NewTicker(interval)
        defer ticker.Stop()
        
        for {
            select {
            case t := <-ticker.C:
                select {
                case ch <- t:
                case <-ctx.Done():
                    return
                }
            case <-ctx.Done():
                return
            }
        }
    }()
    return ch
}
A
Create ticker goroutine that respects context cancellation
B
Use time.Ticker directly
C
Use time.Sleep()
D
Cannot implement
28

Question 28

What is the context cancellation race condition?

go
func badCancellation() {
    ctx, cancel := context.WithCancel(context.Background())
    
    go func() {
        // Race: cancel() might be called before this goroutine starts
        <-ctx.Done()
        fmt.Println("Cancelled")
    }()
    
    // This might execute before goroutine starts
    cancel()
}
A
Goroutines might miss cancellation if started after cancel() is called
B
Deadlock
C
Memory leak
D
No problem
29

Question 29

How do you implement context with metadata?

go
type metadataKey struct{}

type Metadata struct {
    UserID    string
    RequestID string
    TraceID   string
}

func WithMetadata(ctx context.Context, meta Metadata) context.Context {
    return context.WithValue(ctx, metadataKey{}, meta)
}

func GetMetadata(ctx context.Context) Metadata {
    if meta, ok := ctx.Value(metadataKey{}).(Metadata); ok {
        return meta
    }
    return Metadata{}
}
A
Store structured metadata in context using typed keys
B
Use global variables
C
Use channels
D
Cannot store metadata
30

Question 30

What is the context.Background() misuse?

go
func longRunningService() {
    // Wrong: never cancels
    ctx := context.Background()
    
    for {
        doWork(ctx)
        time.Sleep(time.Minute)
    }
}
A
Using Background() for long-running operations that should be cancellable
B
Using in main()
C
Using in tests
D
No misuse
31

Question 31

How do you implement timeout with retry using context?

go
func retryWithTimeout(ctx context.Context, operation func() error, maxRetries int) error {
    for i := 0; i < maxRetries; i++ {
        opCtx, cancel := context.WithTimeout(ctx, time.Second)
        err := operation()
        cancel()
        
        if err == nil {
            return nil
        }
        
        if ctx.Err() != nil {
            return ctx.Err()  // Parent context cancelled
        }
        
        time.Sleep(time.Duration(i) * 100 * time.Millisecond)  // Backoff
    }
    return errors.New("max retries exceeded")
}
A
Create timeout context for each retry attempt, respect parent cancellation
B
Use single timeout
C
Use time.Sleep()
D
Cannot implement
32

Question 32

What is the context.WithValue() anti-pattern?

go
func badValueUsage(ctx context.Context) {
    // Wrong: using string keys
    ctx = context.WithValue(ctx, "user", "alice")
    ctx = context.WithValue(ctx, "user", "bob")  // Overwrites!
    
    // Later
    user := ctx.Value("user").(string)  // Gets "bob", not "alice"
}
A
Using string keys that can collide and be overwritten
B
Using typed keys
C
Using helper functions
D
No anti-pattern
33

Question 33

How do you implement a context-aware semaphore?

go
func acquireSemaphore(ctx context.Context, sem chan struct{}) error {
    select {
    case sem <- struct{}{}:
        return nil
    case <-ctx.Done():
        return ctx.Err()
    }
}

func releaseSemaphore(sem chan struct{}) {
    <-sem
}
A
Use select with semaphore channel and ctx.Done() for cancellable acquisition
B
Use sync.Mutex
C
Use sync.WaitGroup
D
Cannot implement
34

Question 34

What is the context chain lookup cost?

A
O(n) where n is chain depth for Value() lookups
B
O(1)
C
O(log n)
D
No cost
35

Question 35

What is the most important context best practice?

A
Always pass context as first parameter, check ctx.Done() in goroutines, use WithCancel/WithTimeout/WithDeadline appropriately, avoid deep value chains
B
Never use context
C
Use context.Background() everywhere
D
Store everything in context values

QUIZZES IN Golang