In the back-end development, the problem analysis is usually the request level, if the log can be filtered through a unique request number, it can bring a lot of convenience to the analysis problem. Our project also wants to embed the request number in the request-related log.
Golang provides a context for storing kv pairs in http.request, which we can use to store request-related data. At the request entry, we store the unique Requstid in the context and take the value out to print where we need to call it later. If the log is printed in the controller, this is good handling, HTTP. The request is entered as a parameter. But what if it's on the lower level? For example, in model or even some tool classes. We can certainly give each method a parameter, which is passed down the context layer by the caller, but this approach is obviously not elegant enough.
So does Golang provide a static solution to get the current context? The answer is in the negative. Is there a mechanism like threadlocal to get the goroutine context? The answer, too, is negative.
The reason is that Andrew Gerrand that "the problem is more problematic than solving problems" by means of the threading context.
We wouldn ' t even be has this discussion if thread local storage wasn ' t useful. But every feature comes at a cost, and in my opinion the cost of threadlocals far outweighs their benefits. They ' re just not a good fit for Go.
Not only does the official not provide such a method, but also spares no effort to make it impossible for a third party to provide--golang with any method that will allow you to learn about the current Goroutineid.
However, where there is oppression, there is resistance. There are also third-party libraries that do similar functions.
The first is a library that makes a way to get the current goroutine, Https://github.com/bradfitz/http2/blob/dc0c5c000ec33e263612939744d51a3b68b9cece/gotrack.go
The principle is to use the runtime. string format for Stack
You can see that something similar to Goroutineid was printed at the beginning of the stack. With the goroutineid,goroutine of the local storage implementation of the way is also logical, as long as the context stored in the Goroutineid as a key map can be.
In addition, there is a library jtolds/GLS, it is more unique way of implementation. Under the runtime package, there is a callers method to get the list of PCs for the current call stack. This GLS library is using this callers method.
GLS Library pre-defined 16 can be nested empty methods, the caller needs to use the goroutinelocal function, need to use the root method of this function as a parameter into the GLS, GLS in order to generate unused Goroutineid, The Goroutineid is then planted into the call stack. The specific method is to use the 16 empty methods described above, each method used or not represent a bit of 0 or 1, and finally through the 16 methods encoded into 16 bit goroutineid. Decoding, only through the callers method to obtain a list of PCs, and 16 methods of the PC to match can decode the Goroutineid.
The first approach takes advantage of the Golang print format, although this print format is unlikely to change in the future version of Golang, but after all nausea; the second method of brain loop Qing Qi, there seems to be no limitations, but to use in production, or forget it.