

Go Concurrency Patterns: Context - campoy
http://blog.golang.org/context

======
mjibson
From the article:

> 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 pattern demonstrates a fundamental difference between Go and languages
that encourage thread-state data. The arguments for thread-state include not
requiring all functions to pass such a context variable, since it is
(hopefully) already populated in the thread state. The hopefully part is where
thread-state becomes unpleasant, because if you want to do concurrent work,
you must pass one thread's state to the other. The other thread has no
guarantee that it is there, so the programmer must either hope it is or verify
it, which is annoying.

The context-passing style doesn't require that kind of hope, but does require
each function to pass the context to another. When I was working on a medium-
sized go project, I would often need a context deep in the stack, and be
forced to add it to many functions up the tree. Hence, having the standard
that all functions get the context always seems excellent because it is no
longer something to think or worry about and doesn't increase code length by
an unreasonable amount.

I heartily agree with this recommendation and will be using it going forward
in my go projects.

~~~
trhway
>Hence, having the standard that all functions get the context always seems
excellent because it is no longer something to think or worry about and
doesn't increase code length by an unreasonable amount.

how about new paradigm - context-oriented programming :) where, like
"this/self" in OOP, ctx is always present. And looking through the posted
article Google is somewhat there with context [instance level] kind of
inheritance (the context tree)

~~~
mhogomchungu
> how about new paradigm - context-oriented programming :) where, like
> "this/self" in OOP, ctx is always present.

This is how OOP in C is done though usually its done with the context being an
opaque object.

Having functions with multiple arguments that depends on other functions with
multiple arguments that depends on yet other functions with multiple arguments
will result is very hard to manage function dependencies sooner or later and
"context-oriented-programming" solves this problem very nicely.

A function that takes a single argument as a pointer to a struct can be
extended indefinitely without breaking the function API.A function that takes
its arguments by individual arguments will break everytime it need to be
extended by an additional argument.

------
mg74
How is this Context supposed to work with middleware packages that build on
the standard Go http interface? Seems to me that you have to declare Context
as a parameter to your functions t o use it. Am I misreading something?

~~~
2mur
Probably something like:

    
    
        // h already has a context.Context in scope through similar
        func MyHandler (ctx context.Context, h http.Handler) http.Handler {
           return http.HandlerFunc(func (rw http.ResponseWriter, req *http.Request) {
               // do stuff before handler
               h.serveHttp(rw, req)
               // do stuff after handler
           })
        }
    

then you can just chain your handlers and pass through a shared context

~~~
carbocation
In Interpose, that's exactly the pattern I use to pull in methods that require
context while still satisfying the http.Handler interface (e.g.,
[https://github.com/carbocation/interpose/blob/master/example...](https://github.com/carbocation/interpose/blob/master/examples/menagerie/ascendinginteger.go)
), so it seems that this pattern would work well with Google's Context.

------
jonathanyc
I am not too sure about all of this. I like the idea of some sort of format
for specifying when long-running potentially blocking function calls might
end, but creating an entire external package for that purpose feels to me a
bit architecture-astronaut-like.

I did think it seemed nice as a pattern, but not as a library... then I got to
the idea of a black box for context values. That really concerns me. If a
function and a function called by that function both depend on some sort of
parameter, why not just specify it as an argument like everything else? If it
were somehow possible to only have request handling related functions for a
specific application require a context value, that would make sense, but
requiring _every_ function called in the process of handling a request to have
a ctx value as its first parameter? That seems dangerously infectious, and
like using a rake to scratch an itch.

I'll have to wait and see how libraries implement this in practice, but I hope
most libraries will continue to just follow the simple, elegant route - if a
function may block, document it, and let the caller handle putting it in a
goroutine, instead of creating yet more boilerplate.

------
skybrian
It's not type-safe of course. Each function taking a Context has an implicit
interface (the required key-value pairs that the caller must provide in the
context) and failing to provide an expected binding will likely result in a
runtime error.

This is why dependency injection frameworks like Guice and Dagger went with a
different approach: they provide environment values to a class's constructor
using reflection. Then the framework can do type checking at startup (for
Guice) or compile time (for Dagger).

However, that has different costs: it requires a class per component instead
of a function per component, and the framework is more complicated. This is an
engineering tradeoff and apparently the developers of Context decided on
simplicity.

~~~
supersillyus
I read that they have static analysis tools to track the flow of Contexts,
making it much easier to verify that Contexts are threaded through correctly,
which can make things a bit safer statically. It seems Go-like I guess:
instead of language support for that sort of type system, simple enough lang
and good enough tooling to implement the analysis externally.

~~~
Sajmani
Yes, we are working on static analysis and automated refactoring tools. We
will make them available publicly when they are ready, but that won't be very
soon. We wanted to publicize Context now to encourage people to start using it
and incorporating it into new code and frameworks.

------
pothibo
I didn't know this existed until now. I believe this might be exactly what I
need to finish my personal project
[https://github.com/pothibo/irrigation/tree/master/lib/osmosi...](https://github.com/pothibo/irrigation/tree/master/lib/osmosis)

------
saj1th
Does this mean new packages/bridges that supports context.Context getting
released for back-end datastores like elasticsearch, aws etc?

