Skip to main content

How to use contexts in Go

· 2 min read
  • example
    • request URL in a web app
    • connection status e.g. to stop processing when the client disconnects or times out
  • context package
  • context.TODO() creates an empty placeholder context
  • context.Background also creates an empty context
    • deciding which to use is about signaling intent to other developers
    • use Background when you "intend to start a known context"
    • it's a good default option if you aren't sure
  • each layer of an app can add its own information to the context using context.WithValue(ctx, k, v) to create a new context containing that new value
    • this new context will have the original context as the "parent context"
    • contexts are immutable
  • When to use a value in a context vs explicit param
    • depends on what the function is doing with the value
    • e.g. if you have a function that explicitly operates on a username, you should pass that in rather than relying on the context
    • mostly about signaling developer intent
  • Ending a context
    • using Done returns a channel that can be watched for values. it will never be written to until the context is done so you can check it to know when to stop processing
    • can only perform one channel operation per select but can put that select in a loop
    • adding default to the select will keep it from blocking
    • in the example of a loop that tries to either read from Done or from another channel, default just means it starts another loop immediately instead of waiting. This is called a "busy loop". The external behavior is the same though
    • context.WithCancel returns (new context, cancellation function)
      • canceling a context does not automatically cancel the parent context
    • context canceled is a common error in http apps when the client disconnects mid-response
  • context.WithDeadline
    • will cancel context automatically
    • error will be context deadline exceeded
    • there is a convenience wrapper around this called context.WithTimeout

References