liveBook · Manning

Context

As explained in Go in Practice, Second Edition

A Go context is a request- or operation-scoped value that carries deadlines, cancellation signals, and associated key-value data across function calls.

A Go context carries request- or operation-scoped values and lifecycle signals across function calls. It supports deadlines, timeouts, cancellation callbacks, and shared state, especially in concurrent programs and HTTP servers. section 6.1.2 section 8.1.2

Use contexts to control work and pass narrowly scoped request data:

  • Create a cancellable context with context.WithCancel and retain the returned cancel function. section 6.1.2
  • Call cancel when the operation ends; discarding it can create a context leak and memory leak. section 6.1.2
  • Use r.Context in HTTP handlers when work must observe the request lifecycle or its deadline. section 8.1.2
  • Attach request-scoped values with context.WithValue and retrieve them with Value, while recognizing that handler structs can provide an alternative for shared dependencies. section 8.1.2

HTTP middleware carrying request state

A middleware checks the request’s user agent, stores the accepted value with context.WithValue, replaces the request with r.WithContext, and lets the next handler read it through r.Context().Value. The same pattern can support reusable request checks such as authentication. section 8.1.2

Listing 8.5 Sharing state via context
package main

import (
    "context"
    "fmt"
    "net/http"
    "regexp"
)

var validAgent = regexp.MustCompile(`(?i)(chrome|firefox)`)   #1

func uaMiddleware(next http.HandlerFunc) http.HandlerFunc {

return func(w http.ResponseWriter, r *http.Request) {       #2
        userAgent := r.UserAgent()
        if !validAgent.MatchString(userAgent) {     #3
            w.WriteHeader(http.StatusBadRequest)
            return
        }
        ctx := context.WithValue(r.Context(), "agent", userAgent)
        r = r.WithContext(ctx)               #4
        next(w, r)                       #5
    }
}

func uaStatusHandler(w http.ResponseWriter, r *http.Request) {
    ua := r.Context().Value("agent").(string)              #6
    fmt.Fprint(w, fmt.Sprintf("congratulations, you 
    are using: %s", ua))                                  #7
}

func main() {
    http.HandleFunc("GET /withcontext", 
    uaMiddleware(uaStatusHandler))                                          #8
    if err := http.ListenAndServe(":8000", nil); err != nil {
        panic("could not start server")
    }
}

Inspect the complete middleware example that validates a user agent, adds it to the request context, and reads it in the downstream handler. section 8.1.2

How Go in Practice, Second Edition covers it

How deep it goes
Demonstrates creation, cancellation, deadline handling, value propagation, and middleware integration through runnable HTTP examples.
Examples
Uses cancellable background contexts, user-agent middleware, timeout handlers, and PostgreSQL-backed HTTP handlers.
What you can do after
Operate HTTP request lifecycles, propagate scoped values, enforce deadlines, and diagnose discarded cancellation functions with go vet.
How it connects
Connects contexts with concurrency, HTTP servers, middleware, request lifecycles, timeouts, and database access.

Also explained in

Compare how 7 books explain context →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go in Practice, Second Edition. The section links point to the parts of the book it draws on.