{"id":16504527,"url":"https://github.com/cosmos72/gls","last_synced_at":"2025-03-21T08:31:03.560Z","repository":{"id":57486120,"uuid":"131521381","full_name":"cosmos72/gls","owner":"cosmos72","description":"Fast goroutine local storage","archived":false,"fork":false,"pushed_at":"2023-10-20T16:27:09.000Z","size":14,"stargazers_count":25,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-17T22:54:46.932Z","etag":null,"topics":["go","goroutine-safe","thread-local","tls"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cosmos72.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-29T19:00:24.000Z","updated_at":"2024-08-11T01:13:04.000Z","dependencies_parsed_at":"2023-10-20T17:49:56.501Z","dependency_job_id":null,"html_url":"https://github.com/cosmos72/gls","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosmos72%2Fgls","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosmos72%2Fgls/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosmos72%2Fgls/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosmos72%2Fgls/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cosmos72","download_url":"https://codeload.github.com/cosmos72/gls/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244764831,"owners_count":20506714,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","goroutine-safe","thread-local","tls"],"created_at":"2024-10-11T15:03:43.474Z","updated_at":"2025-03-21T08:31:02.691Z","avatar_url":"https://github.com/cosmos72.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"gls\n===\n\nFast goroutine local storage\n\n### WARNING ###\n\nThere is extensive documentation and discussion on why implementing and using\nthread-local storage in Go - actually, goroutine-local storage - is a bad idea.\n\nSee for example the [Go FAQ on goroutine id](https://golang.org/doc/faq#no_goroutine_id)\nand [context.Context](https://blog.golang.org/context), which is how you're encouraged\nto solve problems that would require a goroutine-local storage.\n\nThe main obstacle in adopting `context.Context` is that *all* of your functions\nmust have a new first argument. So, if that horrifies you or is simply not feasible\nfor your use case, feel free to ignore this warning and read on.\n\nJust remember that, if some Go programmers frowns at your use of goroutine-local\nstorage, there are good reasons.\n\n### Why? ###\n\nTo retrieve per-goroutine data that some function did not - or could not -\npass through the call chain, down to where you need it.\n\nOther goroutine-local libraries, as [jtolds/gls](https://github.com/jtolds/gls)\nand [tylerb/gls](https://github.com/tylerb/gls) explain the reasons\nand use cases for goroutine-local storage more in detail.\n\n### Status ###\n\nBeta.\n\nLightly tested on 386, amd64, arm, arm64, mips, ppc64le with Go 1.10.1.  \nOther architectures (mipsle, mips64, ppc64, riscv64, s390x) supported in theory but not tested.\n\n### How it works ###\n\nGo runtime has an internal, i.e. unexported, goroutine-local `runtime.g` struct.\nIt is used for several purposes, including `defer()`, `recover()`,\nby the goroutine scheduler, and it even has an unexported `goid` field,\ni.e. a goroutine ID.\n\nSeveral other goroutine-local libraries extract this goroutine ID\nwith various tricks, most notably from `runtime.Stack()` textual output.\n\nInstead, we use a tiny bit of assembler code to retrieve the address\nof the `runtime.g` struct and return it converted to an opaque `uintptr`.\n\nWe use it as the key in a global variable containing per-goroutine data.\n\nThis is also **fast**, probably orders of magnitude faster than most other solutions.\n\n#### Why not the same goroutine ID? ####\n\nTo avoid fiddling with the internal layout of `runtime.g` struct,\nwe only take its address.\n\nAccessing the `goid` field would require knowing its offset within the struct,\nwhich is both tedious and error-prone to retrieve, since it's an unexported\nfield of an unexported struct type.\n\n### Documentation ###\n\nSee the autogenerated API docs at http://godoc.org/github.com/cosmos72/gls\n\n### License ###\n\nBSD 3-Clause License\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcosmos72%2Fgls","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcosmos72%2Fgls","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcosmos72%2Fgls/lists"}