func WithValue
func WithValue(parent Context, key, val any) ContextWithValue returns a derived context that points to the parent Context. In the derived context, the value associated with key is val.
Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions.
The provided key must be comparable and should not be of type string or any other built-in type to avoid collisions between packages using context. Users of WithValue should define their own types for keys. To avoid allocating when assigning to an interface{}, context keys often have concrete type struct{}. Alternatively, exported context key variables’ static type should be a pointer or interface.
We’ve already talked pretty extensively about when to use, and not use, context.WithValue, and how to select context keys. So we won’t repeat that here. Instead, we’ll look at the example provided in the docs, and disect it a bit.
Example
This example demonstrates how a value can be passed to the context and also how to retrieve it if it exists.
import ( "context" "fmt" ) func main() { type favContextKey string f := func(ctx context.Context, k favContextKey) { if v := ctx.Value(k); v != nil { fmt.Println("found value:", v) return } fmt.Println("key not found:", k) } k := favContextKey("language") ctx := context.WithValue(context.Background(), k, "Go") f(ctx, k) f(ctx, favContextKey("color")) }
This short example shows a good example of a custom context key type, based on string, as we’ve previously discussed.
Then it shows a utility function, f, that simply prints the value associated with a context key, or a message that the key was not found.
Then it calls context.WithValue to create a new context with a value associated with the key favContextKey("language"). Then finally it calls f twice, once with a key that exists, and once with a key that does not.
I think the main atypical thing to point out here is that it’s rare that you’ll retrieve a value from a context, and not use a type assertion to convert it to an expected type. Because this example simply prints the value, it doesn’t need to do that. But in practice, you’ll almost always want to do something like this:
if v, ok := ctx.Value(k).(string); ok {
fmt.Println("found value:", v)
return
}