Golang Context Package Quiz
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.
Question 1
What is the context package in Golang?
import "context"
ctx := context.Background()
// ctx carries deadlines, cancellation, and valuesQuestion 2
What is the difference between context.Background() and context.TODO()?
func main() {
ctx := context.Background() // For main functions, tests
func() {
ctx := context.TODO() // When unsure which context to use
}()
}Question 3
How do you implement cancellation with context?
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()Question 4
How do you set a deadline with context?
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")
}Question 5
How do you set a timeout with context?
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// ctx will be cancelled after 5 secondsQuestion 6
How do you pass values through context?
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 ""
}Question 7
What happens when a context is cancelled?
ctx, cancel := context.WithCancel(context.Background())
select {
case <-ctx.Done():
err := ctx.Err()
fmt.Println("Error:", err) // context canceled
}Question 8
How do you propagate context through function calls?
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
}Question 9
What is context inheritance?
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 tooQuestion 10
How do you handle context in HTTP handlers?
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)
}
}Question 11
What is the problem with this context usage?
func badHandler() {
ctx := context.Background()
go longRunningTask(ctx) // Never cancelled
}
func longRunningTask(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
default:
// work
}
}
}Question 12
How do you implement a context-aware worker pool?
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()
}Question 13
How do you check if a context has a deadline?
deadline, ok := ctx.Deadline()
if ok {
fmt.Printf("Deadline: %v\n", deadline)
} else {
fmt.Println("No deadline")
}Question 14
What is context.WithValue best practice?
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 ""
}Question 15
How do you implement cascading cancellation?
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
}
}Question 16
What is the context leak problem?
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
}Question 17
How do you implement timeout for database queries?
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
}
}Question 18
What is the context.TODO() usage pattern?
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)
}Question 19
How do you handle multiple contexts in a function?
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)
}Question 20
What is the context.Value() lookup behavior?
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"Question 21
How do you implement graceful shutdown with context?
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)
}Question 22
What is the problem with storing pointers in context?
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)
}()
}Question 23
How do you implement request tracing with context?
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)
}Question 24
What is the context tree pattern?
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
}Question 25
How do you handle context in testing?
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")
}
}Question 26
What is the context.Value() performance consideration?
Question 27
How do you implement a context-aware ticker?
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
}Question 28
What is the context cancellation race condition?
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()
}Question 29
How do you implement context with metadata?
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{}
}Question 30
What is the context.Background() misuse?
func longRunningService() {
// Wrong: never cancels
ctx := context.Background()
for {
doWork(ctx)
time.Sleep(time.Minute)
}
}Question 31
How do you implement timeout with retry using context?
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")
}Question 32
What is the context.WithValue() anti-pattern?
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"
}Question 33
How do you implement a context-aware semaphore?
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
}Question 34
What is the context chain lookup cost?
Question 35
What is the most important context best practice?
