What does this print? (context value keys)
Question 268MediumGo 1.22 to 1.25
type ctxKey string
func main() {
ctx := context.WithValue(context.Background(), ctxKey("user"), "alice")
ctx = context.WithValue(ctx, ctxKey("user"), "bob")
child, cancel := context.WithCancel(ctx)
defer cancel()
fmt.Println(child.Value(ctxKey("user")))
fmt.Println(child.Value("user"))
fmt.Println(child.Value(ctxKey("missing")))
}
Output:
bob
<nil>
<nil>
- bob:
Valuewalks up from the node where you call it, and the nearest match wins. The secondWithValuehides the first; it does not replace it, and "alice" is still stored further up the chain. TheWithCancellayer passesValuecalls straight to its parent. - <nil> for
"user": the key is an untyped string constant that becomesstring, while the stored key's dynamic type isctxKey. Different types mean the interfaces are not equal. - <nil> for a missing key:
Valuenever panics. It returnsnil, so always use the comma-ok type assertion.
More on Context
- Q266What does this print? (WithTimeoutCause and its cancel function)
- Q267Why should context keys use an unexported custom type instead of a string? Show the idiomatic pattern.
- Q269How is Value lookup implemented, and what are its performance implications?
- Q270What belongs in context values and what doesn't?
- Q271Why is storing a context.Context in a struct considered an anti-pattern? Are there exceptions?
- Q272context.Background() vs context.TODO(): when do you use each, and why not pass nil?