WhatWhyScenariosHow to useCreate a contextUse withValue to share dataUse cancellation to terminate all process in the same pipelineUse timeout and deadline so that app does not wait foreverEmbed zerolog logger in contextReference
What
A
Context carries deadlines, cancellation signals, and other request-scoped values across API boundaries and goroutines.Why
- Timeout
- Deadline
- Channel
- Share data
Scenarios
- Web request
- HTTP request
- gRPC
How to use
Create a context
ctx, cancel := context.Background()
ctx, cancel := context.TODO() // less commonUse withValue to share data
Imagine a
map inside context.package main
import (
"context"
"fmt"
)
func main() {
ctx := context.Background()
ctx = addValue(ctx)
readValue(ctx)
}
func addValue(ctx context.Context) context.Context {
return context.WithValue(ctx, "key", "test-value")
}
func readValue(ctx context.Context) {
val := ctx.Value("key")
fmt.Println(val) // test-value
}Use cancellation to terminate all process in the same pipeline
Ex: A client close their browser, then we should stop querying data from the database.
If cancellation is triggered, we receive messages from
ctx.Done(). operation1 failed after 100 ms, and then operation2 is halted.func operation1(ctx context.Context) error {
// Let's assume that this operation failed for some reason
// We use time.Sleep to simulate a resource intensive operation
time.Sleep(100 * time.Millisecond)
return errors.New("failed")
}
func operation2(ctx context.Context) {
// We use a similar pattern to the HTTP server
// that we saw in the earlier example
select {
case <-time.After(500 * time.Millisecond):
fmt.Println("done")
case <-ctx.Done():
fmt.Println("halted operation2")
}
}
func main() {
// Create a new context
ctx := context.Background()
// Create a new context, with its cancellation function
// from the original context
ctx, cancel := context.WithCancel(ctx)
// Run two operations: one in a different go routine
go func() {
err := operation1(ctx)
// If this operation returns an error
// cancel all operations using this context
if err != nil {
cancel()
}
}()
// Run operation2 with the same context we use for operation1
operation2(ctx)
}Use timeout and deadline so that app does not wait forever
// The context will be cancelled after 3 seconds
// If it needs to be cancelled earlier, the `cancel` function can
// be used, like before
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
// Setting a context deadline is similar to setting a timeout, except
// you specify a time when you want the context to cancel, rather than a duration.
// Here, the context will be cancelled on 2009-11-10 23:00:00
ctx, cancel := context.WithDeadline(ctx, time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC))Embed zerolog logger in context
logger := zerolog.Ctx(ctx)
ctx = logger.WithContext(ctx)