Golang / GoLang Concurrency Mastery Interview Questions
Write a complete example of implementing operation timeouts in Go using select.
Timeouts are critical for preventing goroutine leaks in service calls. The idiomatic Go approach uses context.WithTimeout (production preferred) or time.After (quick one-off). A crucial detail: the result channel must be buffered to avoid a goroutine leak when the timeout fires first.
// Pattern 1: context.WithTimeout (production preferred) func callService(ctx context.Context, req Request) (Response, error) { ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() // ALWAYS: releases resources even on happy path result := make(chan Response, 1) // buffered â prevents goroutine leak! errCh := make(chan error, 1) go func() { resp, err := doServiceCall(ctx, req) // honours context cancellation if err != nil { errCh <- err; return } result <- resp }() select { case resp := <-result: return resp, nil case err := <-errCh: return Response{}, err case <-ctx.Done(): return Response{}, fmt.Errorf("service: %w", ctx.Err()) } } // Pattern 2: time.After (simpler for standalone use) func computeWithTimeout(input int) (int, error) { result := make(chan int, 1) // MUST be buffered â see below go func() { result <- expensiveCompute(input) }() select { case v := <-result: return v, nil case <-time.After(3 * time.Second): // The goroutine is NOT killed â it still runs to completion // Buffered channel lets it send and exit without blocking return 0, errors.New("computation timed out") } } // WHY unbuffered channel leaks: // result := make(chan int) â unbuffered // If timeout fires first, the goroutine blocks forever on 'result <-' // (nobody receives) â GOROUTINE LEAK
More Related questions...