gls

package module
v0.0.0-...-ab70a82 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2016 License: MIT Imports: 4 Imported by: 0

README

Goroutine Local Storage

Similar to Thread Local Storage, but for Go routines.

Problem solved

Example: tracing HTTP Request

In the request handler, it will perform complicated work invoking many functions. Sometimes, it's difficult and even impossible (through third-party layer) to pass *http.Request all the way down to every function called. But we want most of the functions be able to access the HTTP request, or at least be aware of some information in the HTTP request (e.g. RequestId). With gls, we don't need to pass request to every function which is still able to get the request using gls.Get().

Usage

type Context struct {
    ...
}

func myWork() {
    context := gls.Get().(*Context)
    ...
}

func handler(req *Request) {
    context := contextFromRequest(req)
    gls.With(context, myWork)
}

gls.Get() requires gls.With called, otherwise it will panic. So it's guaranteed the returned value is present. To prevent panic, use gls.GetSafe() which returns nil if gls.With is never called.

The context doesn't go across go routines. If the request must be handled in separate go routines, the context should be forwarded. A helper gls.Go is provided to spawn a go routine with current context forwarded:


func workerFn() {
    // this is in a separate go routine
    context := gls.Get().(*Context)
}

func myHandler() {
    gls.Go(workerFn)
}

This above code is equivalent to:

func workerFn() {
    context := gls.Get().(*Context)
}

func myHandler() {
    context := gls.Get().(*Context)
    go gls.With(context, workerFn)
}

How it works

Because Go routine runs on arbitrary OS thread, the functions in the same Go routine may run on different OS threads from time to time, the Thread Local Storage doesn't solve the problem. The implementation uses stack trace of current Go routine to locate a special function call with magic function name (containing a UUID). By parsing the arguments (pointer values) passed to the function, we can find the context associated with current Go routine.

Supported platforms and architectures

The implementation is a little different on 32-bit/64-bit architectures, because the size of uint passed in the function is different.

Limitations

runtime.Stack returns maximum _TracebackMaxFrames = 100 (see src/runtime/runtime2.go and src/runtime/traceback.go) frames, gls.Get will fail to find the context if the stack is too deep. Keep this in mind when using this library.

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Get

func Get() interface{}

func GetSafe

func GetSafe() interface{}

func Go

func Go(fn func())

func With

func With(data interface{}, fn func())

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL