WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Go · Advanced · question 51 of 100

How can you use ’context’ package for cancellation, timeouts, and passing request-scoped data?

📕 Buy this interview preparation book: 100 Go questions & answers — PDF + EPUB for $5

The ‘context‘ package in Go is a powerful mechanism for managing and controlling the lifetime of requests, providing cancelation, timeouts, and passing request-scoped data. Let me explain each use case in detail:

1. Cancellation:

A common use case for the context package is to cancel requests that have potentially hung or are taking too long to complete. The ‘context.WithCancel‘ function is used to create a new ‘Context‘ with a cancel function. To cancel the request, the cancel function can be called by any part of the program.

Here’s an example:

package main

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

func longRunningTask(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            fmt.Println("Task was canceled")
            return
        default:
            fmt.Println("Task is still running")
            time.Sleep(1 * time.Second)
        }
    }
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    go longRunningTask(ctx)

    time.Sleep(5 * time.Second)
    cancel()
    time.Sleep(2 * time.Second)
}

2. Timeouts:

A timeout can be set on a request using ‘context.WithTimeout‘ function, this function creates a new context that sets a deadline for the request to complete. If the request takes longer than the specified deadline, the context will automatically cancel the request and return a deadline exceeded error.

Here’s an example:

package main

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

func longRunningTask(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            fmt.Println("Task was canceled or reached timeout :", ctx.Err())
            return
        default:
            fmt.Println("Task is still running")
            time.Sleep(1 * time.Second)
        }
    }
}

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

    go longRunningTask(ctx)

    time.Sleep(7 * time.Second)
}

3. Passing request-scoped data:

You can use the context package to store and pass request-scoped data using the ‘context.WithValue‘ function. It returns a new context with the key-value pair stored in it. This allows you to pass data through a request processing pipeline without modifying function signatures and method prototypes.

Here’s an example:

package main

import (
    "context"
    "fmt"
)

type contextKey string

func handleRequest(ctx context.Context, userID string) {
    key := contextKey("user_id")
    ctx = context.WithValue(ctx, key, userID)

    fmt.Println("Handling request for user:", userID)
    processRequest(ctx)
}

func processRequest(ctx context.Context) {
    key := contextKey("user_id")
    if userID, ok := ctx.Value(key).(string); ok {
        fmt.Println("Processing request for user:", userID)
    }
}

func main() {
    ctx := context.Background()
    handleRequest(ctx, "123")
}

In this example, we have used ‘context.WithValue‘ to store the user ID in the context and then used it in the ‘processRequest‘ function.

To sum up, the ‘context‘ package enables you to manage request lifetimes, cancel long-running operations, set timeouts, and pass request-scoped data across different parts of a Go program effectively.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Go interview — then scores it.
📞 Practice Go — free 15 min
📕 Buy this interview preparation book: 100 Go questions & answers — PDF + EPUB for $5

All 100 Go questions · All topics