
Context should go away for Go 2 - beliu
https://faiface.github.io/post/context-should-go-away-go2/
======
axaxs
I agree with the author wholeheartedly. I see the solution that contexts
solve, but it seems like a hacky bolt on that made an otherwise beautiful
language cumbersome.

A solution? Well, I'd had a few passing thoughts but never really vetted them
much or thought of implementation, just throwing things at the wall. I'll
share anyways.

A) A supervisor type system. the 'go' command would return some id, eg

    
    
      x := go runthis()
    

where x is the id. This could then be used to identify, kill, etc things at a
supervisor level.

B) Maybe more esoteric, but treating go routines as implicit channels. There's
a few ways this could go, but it would be similar to the above, except the
return would be an channel. This could allow passing signals to the goroutine,
and also, retrieving values from the goroutine. Eg

    
    
      x := go run()
      y := <-x  // y is the return value of x
      or
      x := go run()
      x <- 1 // terminates the x goroutine

~~~
nemothekid
I don't think A would work because the Go team has been opposed to goroutine
id's, the main detractor being it would be used to create thread local
storage.

I like B, but a major use case for Go is http servers, and I can see that
being awkward when most frameworks don't expose the creation of the
gorountine.

~~~
bbatha
> I don't think A would work because the Go team has been opposed to goroutine
> id's, the main detractor being it would be used to create thread local
> storage.

I find this a weird stance. Idiomatic Go already has pervasive mutable
globals, and life before main. Aside from cancelation the other thing that
`context.Context` poorly abstracts is goroutine local storage. Having go
routine ids and the new sync.Map seem like a backwards compatible way to add
these features to go now.

------
nemothekid
I thought Context was also used to partially solve the "middleware" problem in
http servers. Ex. I have an authorization middleware that takes the http
request parameters and returns an authorization object that is available to
request handlers.

Way back when, Martini solved this problem using reflection (which was met
with vitriol). Other packages solved this with their own handrolled context
object (which was always a map[string]interface{}). I personally always liked
how Martini handled it (you got to "keep" your types), but understandably it
included way too much magic.

~~~
andrewstuart2
The response to Martini always confused me. The language and community (at
first, anyway) was all about terse identifiers, type inference, interface
inference, etc. But then, e.g. with the continual repetition of `if err != nil
{}`, or the "just use stdlib" approach to HTTP, it injects a lot of ceremonial
verbosity back into the ecosystem.

It's not the verbosity that bothers me. It's the arbitrary "verbosity is
bad/verbosity is good" choices that have emerged over time.

~~~
adrianratnapala
Go is consistently anti-magic, but not particularly terse (although the last
time I wrote a Go program next to an equivalent C++ program, it was about 20%
shorter). Instead its syntax strives for whatever the hell Rob Pike means by
"lightness".

Roughly, languages like Java add length by long identifiers and numerous
modifiers to convey that something belongs to particular semantic category
that behaves in a particular way.

Go adds length by having fewers such categories and forcing you to explicitly
code up the behaviour. Short identifiers (and proper use of scoping!) are
orthognal to this, except insofar as they reduce the pain.

~~~
andrewstuart2
I guess I'm thinking mostly about the talk Rob Pike gave called "public static
void" [1], where he probably describes pretty well what "lightness" means to
him, or at least what it meant to him 7 years ago. It seems largely about
verbosity.

[1]
[https://www.youtube.com/watch?v=5kj5ApnhPAE](https://www.youtube.com/watch?v=5kj5ApnhPAE)

------
adrianratnapala
The post is right about the problems with the context object, but is flat
wrong when it claims that the only problem it solves is cancelation.

Cancelation is just one aspect of a generic concern: that a tree of function
calls (and more importantly, RPCs) is a causal chain of events that external
systems (including humans) will want to monitor and control. Trace IDs, auth
tokens and other things need to be propagated somehow, but the code that they
propagate through shouldn't care about them.

So its nice to have context.Context in the standard library so that we don't
have a proliferation of per-library hand-rolled solutions which then have to
be virally propagated.

------
mjevans
I find it interesting that one of the reasons GO refuses to provide a way of
identifying a routine's unique context is to prevent abusing that as a way of
having a session key attached to it... and then the standard libraries go and
make a ctx variable to do EXACTLY that.

I think a solution would probably relate to looking at client connections.

~~~
ithkuil
well, the ctx can be passed between goroutines and still give the ability to
cancel the logical operation, no matter in which goroutine it happens to live

------
pspeter3
I really appreciate the argument in this post. That being said, I wish the
author provided a suggestion of what the cancellation mechanic would be

------
Xeoncross
I like the idea of a standard signaling + param passing struct{}. I don't like
the idea of context.Context slowly taking over the whole golang stdlib.

Then again, I'm positive I'm not as smart as numerous google (and golang)
engineers that have already thrown around ideas so maybe this isn't as big a
deal as it seems.

Not sure I have a solution, but I'd love to see someone come up with one
before context "infects" every function related to I/O.

------
movedx
> Go is a general purpose programming language, just like C, C++, Java or
> Python. For example, I’ve been using Go for about 2 years and I’ve never
> written a single server in it.

This made me twitch because ultimately no argument should start with, "I use
it this way and not that way, so change what you're doing." This was followed
by:

> For this reason, when designing the Go language and it’s standard library,
> we need to approach it from a general purpose language perspective.

My understanding of what's being said here is simply: "I code in Go in this
particular way, so it should be made to suit those requirements." Just because
you don't write servers in Go it doesn't mean others don't. I personally enjoy
the production ready HTTPS server and client on a daily basis. I'm constantly
writing APIs in Go.

All I'm saying here is don't start by saying something doesn't suit your needs
so it needs to change.

The rest of the article was great and gave me more insights into how Go works,
so I thank you for that. And it's possible there is a better solution for
context that should be considered for v2.

Thanks for the good read.

~~~
adrianratnapala
I think it is fair enough for the author to say that since Go is a general
purpose language, its APIs should not end up infected by a viral pattern
needed for servers.

So far, I think Go does a good job of using context.Context where it is needed
and not letting it leak into things like io.Reader. But it is a tricky balance
to strike, because the the author is right that the context pattern is viral
by nature.

~~~
movedx
To a degree I can understand his, and your, view point here. However my
understanding, which could be wrong, is that Go was designed to solve problems
specific to Google. In my opinion that doesn't make it a general purpose
language, that makes it a purpose driven language.

It's general in nature in that you can ignore certain features and use it as a
general language, but ultimately it has a built in HTTPS web server for a
reason, right? And a programmer and an SRE, Context is an excellent idea for
tracing requests through the whole stack -- again, there was a purpose to this
design.

~~~
adrianratnapala
Well I can't speak for Google about why it funds Go. My own observations are
that Rob probably made Go just to be a language that he likes and that it is
also a good fit for the way things are done at Google.

I'm in the odd position that when I go to work as an SRE at Google, I hardly
use Go, but at home I like to use it for hobby projects which are rarely
servers. When I do use Go at work, it is for tools that I run on my
workstation.

So (a) even at Google there is more to life than servers, and (b) Go benefits
from being attractive to people who are not at Google and/or not writing
servers.

~~~
movedx
They fund it because they wanted a language to suit specific goals and be
purpose built to address certain problems. Why does anyone make anything? To
solve a specific set of problems -- positive side effects are a bonus, such as
the solution being general purpose enough that it can be used for other
tasks/problems too.

Ansible has one goal in mind: configuration management. It can also talk to my
toaster and send a Tweet when I pop some bread in there. I guess Ansible is a
"general purpose" configuration management tool, except it's not :-)

Terraform can be used to run a PowerShell script on a Windows box it never
provisioned. I guess it's a scripting framework now.

I think Go can be used as a general purpose language, but that's not how I see
its design ethos. It caters to that crowd, but does have an underlaying goal I
believe.

As long as people are happy and things are working for them then all is well,
I guess.

------
camus2
previous discussion here :

[https://news.ycombinator.com/item?id=14955456](https://news.ycombinator.com/item?id=14955456)

doesn't HN detect dupes?

~~~
0xCMP
It does, but they allow something to be reposted since it's hard to get to the
front. Sometimes it was bad timing, but it's still good.

