contextto help us manage long-running processes.
Storeand returns us a
http.HandlerFunc. Store is defined as:
Fetchmethod to get the data and writes it to the response.
Storewhich we use in a test.
Storecan't finish a
Fetchbefore the user cancels the request.
Storeto cancel the work so update the interface.
dataand a way of knowing it has been told to cancel. We'll also rename it to
SpyStoreas we are now observing the way it is called. It'll have to add
Cancelas a method to implement the
The context package provides functions to derive new Context values from existing ones. These values form a tree: when a Context is canceled, all Contexts derived from it are also canceled.
requestwhich returns us a
cancelfunction. We then schedule that function to be called in 5 milliseconds by using
time.AfterFunc. Finally we use this new context in our request by calling
Storebefore we fetch on every request.
contexthas a method
Done()which returns a channel which gets sent a signal when the context is "done" or "cancelled". We want to listen to that signal and call
store.Cancelif we get it but we want to ignore it if our
Fetchin a goroutine and it will write the result into a new channel
data. We then use
selectto effectively race to the two asynchronous processes and then we either write a response or
*testing.Twhen creating the spy.
Store? What if
Storealso happens to depend on other slow-running processes? We'll have to make sure that
Store.Cancelcorrectly propagates the cancellation to all of its dependants.
contextis that it is a consistent way of offering cancellation.
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.
At Google, we require that Go programmers pass a Context parameter as the first argument to every function on the call path between incoming and outgoing requests. This allows Go code developed by many different teams to interoperate well. It provides simple control over timeouts and cancelation and ensures that critical values like security credentials transit Go programs properly.
Storeand let it be responsible. That way it can also pass the
contextthrough to its dependants and they too can be responsible for stopping themselves.
Storeand that it handles the error that will come from the
Storewhen it is cancelled.
Storeinterface to show the new responsibilities.
datachannel. The goroutine listens for the
ctx.Doneand will stop the work if a signal is sent in that channel.
selectto wait for that goroutine to finish its work or for the cancellation to occur.
contextso make sure you understand what's going on.
httptest.ResponseRecorderdoesn't have a way of figuring this out so we'll have to roll our own spy to test for this.
http.ResponseWriterso we can use it in the test.
contextand relies on the downstream functions to respect any cancellations that may occur.
contextand uses it to cancel itself by using goroutines,
http.ResponseWriterif you need it.
If you use ctx.Value in my (non-existent) company, you’re fired
contextas it feels convenient.
context.Valuesis 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.
context.Value. This makes it statically checked and documented for everyone to see.
The content of context.Value is for maintainers not users. It should never be required input for documented or expected results.
contexteverywhere is a smell, that it's pointing to a deficiency in the language in respect to cancellation. He says it would better if this was somehow solved at the language level, rather than at a library level. Until that happens, you will need
contextif you want to manage long running processes.