You guys are all hilarious. This is pretty much exactly the response I
expected, lol
First off, I just want to point out that I agree that encoding values
on the stack is horrifying. But let me add some replies and
counterpoint :)
> The usual argument against goroutine-local storage is that goroutine
> is essentially never the right level of granularity where you want to
> attach a context.
This is the usual argument, and it's usually right. In fact, I would
personally discourage people from using goroutine-local storage in
nearly every case.
> This was to improve your logs? Use a unique logger per relevant goroutine.
Everything has tradeoffs, and I have the same problem as this guy:
https://groups.google.com/d/msg/golang-nuts/_Vv7Bzn8yH4/HRTU2ah_zM4J
AND the application codebase I'm working in is 88k lines of code and
counting, and I'm not exactly keen on changing every function that
logs anything to take a logging context, or belong to a logging
context, etc. In this case, goroutine-local storage is incredibly
useful. We can now associate what user request caused what log lines
in all areas of our codebase, without having to change *every*
interface.
Again, I'm only using this to improve my log lines. This is *similar*
to Popog's described use case here:
https://groups.google.com/d/msg/golang-nuts/Iyg3lKHV_lQ/DnJNqW9FPI8J
> I also wonder why your library, whose purpose is to provide
> goroutine-local storage, also provides a helper "Go" whose purpose is
> to propagate values across new goroutines.
> Overall usage seems quite unpractical.
Go is beautiful at parallelizing work, and in a few cases in our
codebase, we do a good deal of things in parallel, all in an attempt
to answer an HTTP request. In those cases, we have to kick off new
goroutines but want to preserve the HTTP context we've set up. The
"Go" method propagates our goroutine-local storage to these new
goroutines as we choose.
> You could make this abomination much simpler.
lol, Dave did actually reply directly with an actual suggestion after
this email, and he's right, you can actually get the goroutine id by
interacting with the runtime through C or ASM, but that seemed a
little less portable, and a little less future-proof as the language
changes (I doubt runtime.Callers is going anywhere). But yeah, maybe
that's worth doing to make things faster. I did think about it, as a
similar suggestion was made here:
https://groups.google.com/d/msg/golang-nuts/Iyg3lKHV_lQ/eDW8XX_zLCYJ
Here's a few more objections (and counterpoints):
* Holy crap, you're encoding values on the stack. You're ruining the
readability of the stack.
True, that's totally true. This is just one option in the debugging
tradeoff space.
* This is not very performant. Not only are you adding a bunch of
function calls but you have to call Callers to load a value.
Also completely true. I honestly have no idea what the performance
characteristics of runtime.Callers even is (it's just interacting with
debugging symbols I'm sure), but it doesn't matter to me. Often people
choose reduced performance for better debugging.
* I am horrified at how you are abusing a thing I never expected anyone to do.
Yeah, but check it out, we have really awesome logs now, without
changing tons of code and interfaces to take logging contexts, and
without rewriting any of my hundred libraries. I had a specific
problem that I was unable to find a better solution for. So, yay Go!
One final thought: from a PL perspective, thread or goroutine-local
storage is simply a way of attempting to give you lexically-bound but
dynamically scoped variables in a lexically scoped language. I
*completely* agree that dynamically scoped variables reduce the ease
at which one can reason about her program. But that (1) doesn't mean
they're totally devoid of use, and (2) lexical bindings to dynamically
scoped values address most every concern with dynamic variables. In
fact, in other languages, many things are essentially restricted
dynamically scoped variables, such as the current exception handler,
the current while/for loop to break out of, etc.
If you guys want me to add some kind of "DON'T USE THIS" warning to
the library, that's fine, and I *completely* both understand and
expected the "this is horrific and terrible" responses, but seriously,
this is so useful.
-JT