40

I use Go and Gin to setup my website and want to know the database access time. I use goroutine so if don't use something like thread-local, I must change almost every function to do it. Does Go have a good way to do it?

icza
  • 389,944
  • 63
  • 907
  • 827
modkzs
  • 1,369
  • 4
  • 13
  • 17
  • 1
    It doesn't have thread-local. One alternative is to pass a per-request context around; [Gorilla](http://www.gorillatoolkit.org/pkg/context) and [Google App Engine](https://cloud.google.com/appengine/docs/go/reference#Context) have it. And yes, you can end up needing to pass it through a lot of functions. – twotwotwo Aug 11 '15 at 04:24
  • You can try this package which does allow for thread locals: https://github.com/jwells131313/goethe – jwells131313 Apr 05 '18 at 13:41

2 Answers2

36

The Go runtime and standard libraries do not provide goroutine local storage or a goroutine identifier that can be used to implement goroutine local storage.

The third party gls package implements goroutine local storage in an interesting way. Some find this package horrifying and others think it's clever.

The Go team recommends passing context explicitly as function argument instead of using goroutine local storage. See the context blog post and package documentation for more information.

Charlie Tumahai
  • 113,709
  • 12
  • 249
  • 242
  • I find gls, but I still need to change code with it. It seems that there is no way to do it without change my function. – modkzs Aug 12 '15 at 11:09
  • You can also try this package which does allow for thread local storage: https://github.com/jwells131313/goethe – jwells131313 Apr 05 '18 at 13:41
  • 1
    Context is a brilliant idea! I came across with a situation that I was implementing a JobExecutor which had several workers to execute a bunch of Job functions and I needed to log which worker was running current job. Using goroutine-local vars was my first idea and I was led to this question. This answer pointed out that we should use context, so I thought again. Yes, context is more expressive and straight-forward. My worker can tell its job's running **context** and Job func can retrieve every information it needed from its **running context** – VicX Jan 17 '19 at 04:02
1

See this repo routine, feel your free.

var threadLocal = routine.NewThreadLocal()
var inheritableThreadLocal = routine.NewInheritableThreadLocal()

func main() {
    threadLocal.Set("hello world")
    inheritableThreadLocal.Set("Hello world2")
    fmt.Println("threadLocal:", threadLocal.Get())
    fmt.Println("inheritableThreadLocal:", inheritableThreadLocal.Get())

    // The child coroutine cannot read the previously assigned "hello world".
    go func() {
        fmt.Println("threadLocal in goroutine:", threadLocal.Get())
        fmt.Println("inheritableThreadLocal in goroutine:", inheritableThreadLocal.Get())
    }()

    // However, a new sub-coroutine can be started via the Go/GoWait/GoWaitResul function, and all inheritable variables of the current coroutine can be passed automatically.
    routine.Go(func() {
        fmt.Println("threadLocal in goroutine by Go:", threadLocal.Get())
        fmt.Println("inheritableThreadLocal in goroutine by Go:", inheritableThreadLocal.Get())
    })

    // Wait for the sub-coroutine to finish executing.
    time.Sleep(time.Second)
}
TimAndy
  • 21
  • 3