{"id":17180213,"url":"https://github.com/huandu/go-tls","last_synced_at":"2025-04-12T22:36:01.960Z","repository":{"id":29229423,"uuid":"120262170","full_name":"huandu/go-tls","owner":"huandu","description":"A bit safer approach to implement Thread Local Storage (TLS) for Go 1.7+.","archived":false,"fork":false,"pushed_at":"2021-11-22T02:48:25.000Z","size":36,"stargazers_count":163,"open_issues_count":2,"forks_count":15,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-26T16:39:14.014Z","etag":null,"topics":["experimental","golang","goroutine","hack","thread-local-storage","tls"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/huandu.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}},"created_at":"2018-02-05T06:06:18.000Z","updated_at":"2025-02-11T08:26:49.000Z","dependencies_parsed_at":"2022-08-07T14:15:35.621Z","dependency_job_id":null,"html_url":"https://github.com/huandu/go-tls","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huandu%2Fgo-tls","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huandu%2Fgo-tls/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huandu%2Fgo-tls/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huandu%2Fgo-tls/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/huandu","download_url":"https://codeload.github.com/huandu/go-tls/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248642628,"owners_count":21138352,"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":["experimental","golang","goroutine","hack","thread-local-storage","tls"],"created_at":"2024-10-15T00:29:07.907Z","updated_at":"2025-04-12T22:36:01.938Z","avatar_url":"https://github.com/huandu.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-tls: TLS for any goroutine\n\n[![CircleCI](https://circleci.com/gh/huandu/go-tls.svg?style=shield)](https://circleci.com/gh/huandu/go-tls)\n[![GoDoc](https://godoc.org/github.com/huandu/go-tls?status.svg)](https://pkg.go.dev/github.com/huandu/go-tls)\n    \n\u003e :warning: This package doesn't support Go1.17.* due to Go runtime changes. Don't use this package until [#10](https://github.com/huandu/go-tls/issues/10) is resolved.\n\n_WARNING: It's not recommended to use this package in any production environment. It may crash you at any time. Use `context` instead when possible._\n\nPackage `tls` provides TLS for any goroutine by hijacking `runtime.goexit` on stack. Comparing with other similar packages, this package avoids any potential resource leak in TLS.\n\n## Install\n\nUse `go get` to install this package.\n\n```bash\n    go get github.com/huandu/go-tls\n```\n\n## Use TLS\n\nSet arbitrary data and get it later.\n\n```go\nk := \"my key\"\nv := 1234\ntls.Set(k, tls.MakeData(v))\n\n// Get data by k.\nd, ok := tls.Get(k)\nassert(ok)\nassert(d.Value().(int) == v)\n\n// Get a unique ID for current goroutine.\n// It's guaranteed to be unique.\nid := tls.ID()\n\n// Delete data by k.\ntls.Del(k)\n\n// Reset TLS so that all keys are removed and all data is closed if necessary.\n// It doesn't remove any AtExit handler.\ntls.Reset()\n\n// Completely unload TLS and discard all data and AtExit handlers.\n// If TLS method is called after Unload, a new TLS stub will be created.\n// The ID() will return a different value.\ntls.Unload()\n```\n\nIf the data implements `io.Closer`, it will be called automatically when `Reset` is called or goroutine exits. It's not allowed to use any TLS methods in the `Close` method of TLS data. It will cause permanent memory leak.\n\n## Execute code when goroutine exits\n\n`AtExit` pushes a function to a slice of at-exit handlers and executes them when goroutine is exiting in FILO order. All TLS data is still available when calling at-exit handlers.\n\n`AtExit` doesn't work on main goroutine as it doesn't exit at all.\n\n```go\ntls.AtExit(func() {\n    // Do something when goroutine is exiting...\n})\n```\n\n## Limitations\n\nSeveral limitations so far.\n\n- Works with Go 1.7 or newer.\n- `AtExit` doesn't work on main goroutine, as this goroutine always exits with `os.Exit(0)` instead of calling `goexit`. See `main()` in `src/runtime/proc.go`.\n\n## How it works\n\nIt's quite a long story I don't have time to write everything down right now.\n\nTL; DR. Package `tls` uses goroutine's `g` struct pointer to identify a goroutine and hacks `runtime.goexit` to do house clean work when goroutine exits.\n\nThis approach is relatively safe, because all technics are based on runtime types which doesn't change since Go1.0.\n\nFollowing runtime types are used.\n\n- The `g.stack`: It's the first field of `g`. It stores stack memory range of a `g`.\n- Function symbol table: When Go runtime allocates more stack, it validates all return addresses on stack. If I change `runtime.goexit` to another function pc, runtime will complain it as it's not a valid top of stack function (checked by `runtime.topofstack`). As a workaround, I hacks function symbol table to set `_func.pcsp` of the hacked goexit to `0` to skip checks.\n\n## Similar packages\n\n- [github.com/jtolds/gls](https://github.com/jtolds/gls): Goroutine local storage on current goroutine's stack. We must start goroutines with `Go` func explicitly before using any context methods.\n- [github.com/v2pro/plz/gls](https://github.com/v2pro/plz/tree/master/gls): Use `goid` as a unique key for any goroutine and store contextual information.\n\n## License\n\nThis package is licensed under MIT license. See LICENSE for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuandu%2Fgo-tls","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhuandu%2Fgo-tls","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuandu%2Fgo-tls/lists"}