codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

© 2026 codingstuff.io. All rights reserved.

Built with ❤️ for developers everywhere

/
/
All Tutorials
🐹

Go (Golang)

40 / 72 topics
27Standard Library Overview28IO Package29Net Package30HTTP Package31JSON Package32XML Package33Time Package34OS Package35Fmt Package36Math Package37Regexp Package38Log Package39Flag Package40Context Package41Embed Package
Tutorials/Go (Golang)/Context Package
🐹Go (Golang)

Context Package

Updated 2026-04-20
4 min read

Context Package

The context package in Go is a powerful tool for managing request-scoped data, deadlines, and cancellation signals across multiple goroutines. It's an essential part of writing robust, scalable, and maintainable concurrent applications. This guide will provide you with a comprehensive understanding of the context package, including its purpose, usage patterns, real-world examples, and best practices.

Introduction to Context

In Go, concurrency is managed using goroutines and channels. However, managing the lifecycle of these goroutines can be challenging, especially when dealing with timeouts, deadlines, or cancellation signals. The context package addresses this by providing a way to carry request-scoped data, cancelation signals, and deadlines across API boundaries.

Key Concepts

  1. Context: A context is an immutable value that carries deadlines, cancellation signals, and other request-scoped values across API boundaries.
  2. Cancellation: Contexts can be used to signal the cancellation of a goroutine or a group of goroutines.
  3. Deadline: Contexts can specify a deadline after which operations should be cancelled.
  4. Timeout: A timeout is a special case of a deadline that specifies a duration from the current time.

Creating and Using Contexts

Basic Usage

The context package provides several functions to create contexts:

  • context.Background(): Returns an empty context. It's typically used as the root context for other contexts.
  • context.TODO(): Used when you're not sure what context to use yet, but you need one temporarily.
  • context.WithCancel(parent): Creates a new context that can be cancelled using a cancel function.
  • context.WithDeadline(parent, deadline): Creates a new context with a deadline.
  • context.WithTimeout(parent, timeout): Creates a new context with a timeout.

Example: Creating and Cancelling a Context

package main

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

func main() {
    // Create a root context
    ctx := context.Background()

    // Create a cancellable context
    ctx, cancel := context.WithCancel(ctx)

    // Start a goroutine that listens for cancellation
    go func() {
        select {
        case <-ctx.Done():
            fmt.Println("Goroutine cancelled:", ctx.Err())
        }
    }()

    // Simulate some work
    time.Sleep(2 * time.Second)

    // Cancel the context
    cancel()
}

In this example, a cancellable context is created using context.WithCancel. The goroutine listens for cancellation via the ctx.Done() channel. After 2 seconds, the context is cancelled using the cancel function.

Example: Using Deadline

package main

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

func main() {
    // Create a root context
    ctx := context.Background()

    // Create a context with a deadline
    ctx, cancel := context.WithDeadline(ctx, time.Now().Add(2*time.Second))
    defer cancel()

    // Start a goroutine that listens for cancellation or deadline
    go func() {
        select {
        case <-ctx.Done():
            fmt.Println("Goroutine cancelled or deadline reached:", ctx.Err())
        }
    }()

    // Simulate some work
    time.Sleep(3 * time.Second)
}

In this example, a context with a deadline is created using context.WithDeadline. The goroutine listens for cancellation or the deadline being reached. Since the deadline is set to 2 seconds and the sleep duration is 3 seconds, the context will be cancelled due to the deadline.

Best Practices

  1. Pass Context as the First Parameter: Always pass the context as the first parameter in your functions that require it. This makes it easy to propagate the context throughout your application.

    func fetchData(ctx context.Context, url string) (string, error) {
        // Function implementation
    }
    
  2. Use context.Background() for Root Contexts: Use context.Background() as the root context when creating other contexts. It's a good practice to avoid using context.TODO() unless you're unsure about the context.

  3. Cancel Contexts Properly: Always defer the cancellation of contexts to ensure that resources are released properly, even if an error occurs.

    ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
    defer cancel()
    
  4. Avoid Blocking Operations in Done() Channel: The ctx.Done() channel should not be used for blocking operations. Instead, use it to listen for cancellation signals and handle them appropriately.

  5. Use Context Values Sparingly: While context values can be useful for passing request-scoped data, they should be used sparingly. Overusing them can lead to code that's hard to maintain and understand.

Advanced Usage

Propagating Contexts Across API Boundaries

When designing APIs, it's important to propagate contexts across different layers of your application. This ensures that cancellation signals and deadlines are respected throughout the call stack.

package main

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

func fetchData(ctx context.Context, url string) (string, error) {
    select {
    case <-ctx.Done():
        return "", ctx.Err()
    default:
        // Simulate network delay
        time.Sleep(3 * time.Second)
        return "Data", nil
    }
}

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

    data, err := fetchData(ctx, "http://example.com")
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Data:", data)
    }
}

In this example, the fetchData function takes a context as its first parameter and uses it to check for cancellation. The main function creates a context with a timeout and passes it to fetchData.

Using Context Values

Context values can be used to pass request-scoped data across API boundaries.

package main

import (
    "context"
    "fmt"
)

func fetchData(ctx context.Context, url string) (string, error) {
    userID := ctx.Value("userID")
    fmt.Println("Fetching data for user:", userID)
    // Simulate fetching data
    return "Data", nil
}

func main() {
    ctx := context.Background()
    ctx = context.WithValue(ctx, "userID", 12345)

    data, err := fetchData(ctx, "http://example.com")
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Data:", data)
    }
}

In this example, a context value is set using context.WithValue. The fetchData function retrieves the user ID from the context and uses it to fetch data.

Conclusion

The context package is an essential tool for managing concurrency in Go. It provides a way to carry deadlines, cancellation signals, and request-scoped data across API boundaries, making your applications more robust and maintainable. By following best practices and understanding how to use contexts effectively, you can write efficient and scalable concurrent code in Go.

Remember to always pass context as the first parameter, cancel contexts properly, and avoid overusing context values. With these guidelines, you'll be well-equipped to handle complex concurrency scenarios in your Go applications.


PreviousFlag PackageNext Embed Package

Recommended Gear

Flag PackageEmbed Package