61ddd5d06e | 3 months ago | |
---|---|---|
.. | ||
README.md | 3 months ago | |
go.mod | 3 months ago | |
my_context.go | 3 months ago | |
my_context_test.go | 3 months ago |
README.md
Using Context
Remember that a common pattern of signaling events or completion is using a blocking channel that receives and empty struct. An empty struct has zero memory footprint. It is typically used to signal completion or stopping.
The Context.Done() returns a channel that is closed when this Context is canceled Done() <-chan struct{}
. Contexts have a root and can form a parent child tree structure. A child is "derived" from a parent context and when a Context is cancelled all derived contexts are also canceled. WithCancel and WithTimeout return derived Context values that can be canceled sooner than the parent Context.
Incoming requests to a server should create a Context, and outgoing calls to servers should accept a Context. The chain of function calls between them must propagate the Context, optionally replacing it with a derived Context created using WithCancel, WithDeadline, WithTimeout, or WithValue. When a Context is canceled, all Contexts derived from it are also canceled.
What about Context.Value
The problem with context.Values is that it's just an untyped map so you have no type-safety and you have to handle it not actually containing your value. You have to create a coupling of map keys from one module to another and if someone changes something things start breaking.
In short, if a function needs some values, put them as typed parameters rather than trying to fetch them from context.Value . This makes it statically checked and documented for everyone to see.
Context.Value is good for things like "A trace ID". It's information that is not needed for by every function in the call stack.
Context.Value should inform not control. The content of context.Value is for maintainers not users. It should never be required input for documented or expected results.