0
0
GoHow-ToBeginner · 3 min read

How to Use context.WithTimeout in Go: Simple Guide

Use context.WithTimeout in Go to create a context that automatically cancels after a set time duration. It returns a new context and a cancel function, which you should call to release resources. This helps control how long operations run and handle timeouts gracefully.
📐

Syntax

The context.WithTimeout function creates a new context that cancels automatically after the specified timeout duration. It returns two values: the new context and a cancel function.

  • parent: The original context to derive from, usually context.Background() or context.TODO().
  • timeout: The duration after which the context will be canceled.
  • ctx: The new context with timeout.
  • cancel: A function to cancel the context manually and free resources.
go
ctx, cancel := context.WithTimeout(parent, timeout)
// Use ctx in operations
// Call cancel() when done to release resources
💻

Example

This example shows how to use context.WithTimeout to limit a simulated work operation to 2 seconds. If the work takes longer, the context cancels and the program stops waiting.

go
package main

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

func main() {
	// Create a context with 2-second timeout
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel() // Ensure resources are freed

	// Simulate work that takes 3 seconds
	workDone := make(chan bool)
	go func() {
		time.Sleep(3 * time.Second)
		workDone <- true
	}()

	select {
	case <-workDone:
		fmt.Println("Work completed")
	case <-ctx.Done():
		fmt.Println("Timeout reached:", ctx.Err())
	}
}
Output
Timeout reached: context deadline exceeded
⚠️

Common Pitfalls

Common mistakes when using context.WithTimeout include:

  • Not calling the cancel() function, which can cause resource leaks.
  • Ignoring the context's Done() channel and not handling cancellation properly.
  • Setting a timeout too short or too long for the operation.

Always defer the cancel() call right after creating the context to ensure cleanup.

go
package main

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

func main() {
	// Wrong: Not calling cancel()
	ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)

	// Correct: Call cancel() to free resources
	ctx2, cancel := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel()

	_ = ctx
	_ = ctx2
	fmt.Println("Remember to call cancel() to avoid leaks")
}
Output
Remember to call cancel() to avoid leaks
📊

Quick Reference

FunctionDescription
context.WithTimeout(parent, timeout)Creates a context that cancels after timeout
cancel()Function to cancel the context and free resources
ctx.Done()Channel closed when context is canceled or times out
ctx.Err()Returns error explaining why context was canceled

Key Takeaways

Use context.WithTimeout to limit how long operations run in Go.
Always call the cancel function returned by context.WithTimeout to free resources.
Check ctx.Done() to handle cancellations or timeouts gracefully.
Set timeout durations thoughtfully based on expected operation time.
Use context.WithTimeout with context.Background() or other parent contexts.