{"id":43886933,"url":"https://github.com/go-eden/routine","last_synced_at":"2026-02-06T16:13:15.922Z","repository":{"id":39332183,"uuid":"377742670","full_name":"go-eden/routine","owner":"go-eden","description":"Provides some convenient API, includes Goid(), GetG() and LocalStorage, which is a goroutine's local storage, just like ThreadLocal in other languages.","archived":false,"fork":false,"pushed_at":"2023-03-15T06:41:41.000Z","size":44,"stargazers_count":111,"open_issues_count":3,"forks_count":19,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-06-18T15:28:33.087Z","etag":null,"topics":["goid","goroutine","localstorage","threadlocal"],"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/go-eden.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":"2021-06-17T07:27:48.000Z","updated_at":"2024-05-31T09:23:09.000Z","dependencies_parsed_at":"2024-06-18T15:22:56.341Z","dependency_job_id":"97dd20c6-5f15-4e31-801f-a301edee2af1","html_url":"https://github.com/go-eden/routine","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/go-eden/routine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-eden%2Froutine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-eden%2Froutine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-eden%2Froutine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-eden%2Froutine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-eden","download_url":"https://codeload.github.com/go-eden/routine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-eden%2Froutine/sbom","scorecard":{"id":431692,"data":{"date":"2025-08-11","repo":{"name":"github.com/go-eden/routine","commit":"61f6213048a84878d937e6b506f198a922dc0bb8"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Code-Review","score":0,"reason":"Found 1/23 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2022-0603 / GHSA-hp87-p4gw-j4gq"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 5 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T03:30:14.656Z","repository_id":39332183,"created_at":"2025-08-19T03:30:14.656Z","updated_at":"2025-08-19T03:30:14.656Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29167886,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-06T15:38:29.831Z","status":"ssl_error","status_checked_at":"2026-02-06T15:37:48.592Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["goid","goroutine","localstorage","threadlocal"],"created_at":"2026-02-06T16:13:15.246Z","updated_at":"2026-02-06T16:13:15.913Z","avatar_url":"https://github.com/go-eden.png","language":"Go","readme":"# routine\n\n[![Build Status](https://travis-ci.com/go-eden/routine.svg?branch=main)](https://travis-ci.com/github/go-eden/routine)\n[![codecov](https://codecov.io/gh/go-eden/routine/branch/main/graph/badge.svg?token=R4GC2IuGoh)](https://codecov.io/gh/go-eden/routine)\n[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go\u0026logoColor=white\u0026style=flat)](https://pkg.go.dev/github.com/go-eden/routine)\n\n\u003e [中文版](README_zh.md)\n\n`routine` encapsulates and provides some easy-to-use, high-performance `goroutine` context access interfaces, which can\nhelp you access coroutine context information more elegantly, but you may also open Pandora's Box.\n\n# Introduce\n\nThe `Golang` language has been sparing no effort to shield developers from the concept of coroutine context from the\nbeginning of its design, including the acquisition of coroutine `goid`, the state of the coroutine within the process,\nand the storage of coroutine context.\n\nIf you have used other languages such as `C++/Java/...`, then you must be familiar with `ThreadLocal`, and after\nstarting to use `Golang`, you will definitely feel confused and distressed by the lack of convenient functions similar\nto `ThreadLocal` . Of course, you can choose to use `Context`, let it carry all the context information, appear in the\nfirst input parameter of all functions, and then shuttle around in your system.\n\nThe core goal of `routine` is to open up another path: to introduce `goroutine local storage` into the world of `Golang`\n, and at the same time expose the coroutine information to meet the needs of some people.\n\n# Usage \u0026 Demo\n\nThis chapter briefly introduces how to install and use the `routine` library.\n\n## Install\n\n```bash\ngo get github.com/go-eden/routine\n```\n\n## Use `goid`\n\nThe following code simply demonstrates the use of `routine.Goid()`:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/go-eden/routine\"\n\t\"time\"\n)\n\nfunc main() {\n\tgo func() {\n\t\ttime.Sleep(time.Second)\n\t}()\n\tgoid := routine.Goid()\n\tfmt.Printf(\"curr goid: %d\\n\", goid)\n}\n```\n\nIn this example, the `main` function starts a new coroutine, so `Goid()` returns the main coroutine `1`:\n\n```text\ncurr goid: 1\n```\n\n## Use `LocalStorage`\n\nThe following code simply demonstrates `NewLocalStorage()`, `Set()`, `Get()`, and cross-coroutine propagation\nof `LocalStorage`:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/go-eden/routine\"\n\t\"time\"\n)\n\nvar nameVar = routine.NewLocalStorage()\n\nfunc main() {\n\tnameVar.Set(\"hello world\")\n\tfmt.Println(\"name: \", nameVar.Get())\n\n\t// other goroutine cannot read nameVar\n\tgo func() {\n\t\tfmt.Println(\"name1: \", nameVar.Get())\n\t}()\n\n\t// but, the new goroutine could inherit/copy all local data from the current goroutine like this:\n\troutine.Go(func() {\n\t\tfmt.Println(\"name2: \", nameVar.Get())\n\t})\n\n\t// or, you could copy all local data manually\n\tic := routine.BackupContext()\n\tgo func() {\n\t\troutine.InheritContext(ic)\n\t\tfmt.Println(\"name3: \", nameVar.Get())\n\t}()\n\n\ttime.Sleep(time.Second)\n}\n```\n\nThe results of the upper example are:\n\n```text\nname:  hello world\nname1:  \u003cnil\u003e\nname3:  hello world\nname2:  hello world\n```\n\n# API\n\nThis chapter introduces in detail all the interfaces encapsulated by the `routine` library, as well as their core\nfunctions and implementation methods.\n\n## `Goid() (id int64)`\n\nGet the `goid` of the current `goroutine`.\n\n## `NewLocalStorage()`:\n\nCreate a new instance of `LocalStorage`, its design idea is very similar to the usage of `ThreadLocal` in other\nlanguages.\n\n## `BackupContext() *ImmutableContext`\n\nBack up the `local storage` data of the current coroutine context. It is just an immutable structure that facilitates\nthe transfer of context data.\n\n## `InheritContext(ic *ImmutableContext)`\n\nActively inherit the backed-up context `local storage` data, it will copy the data of other coroutines `BackupContext()`\ninto the current coroutine context, thus supporting the contextual data propagation across coroutines.\n\n## `Go(f func())`\n\nStart a new coroutine and automatically copy all the context `local storage` data of the current coroutine to the new\ncoroutine. Its internal implementation consists of `BackupContext()` and `InheritContext()`.\n\n## `LocalStorage`\n\nRepresents the context variable of the coroutine, and the supported functions include:\n\n+ `Get() (value interface{})`: Get the variable value that has been set by the current coroutine.\n+ `Set(v interface{}) interface{}`: Set the value of the context variable of the current coroutine, and return the old\n  value that has been set before.\n+ `Del() (v interface{})`: Delete the context variable value of the current coroutine and return the deleted old value.\n\n**Tip: The internal implementation of `Get/Set/Del` adopts a lock-free design. In most cases, its performance should be\nvery stable and efficient.**\n\n# Garbage Collection\n\nBefore the `v1.0.0` version, `routine` will setup a backgrount timer to scan all go-routines intervally, and find the exited routine to clean the related `LocalStorage` data.\n\nAfter the `v1.0.0` version, `routine` will register a `finalizer` to listen the lifecycle of `runtime.g`. \n\nAfter the coroutine exits, when runtime's GC running, the `finalizer` mechanism of `runtime` will actively remove the useless `LocalStorage` `Data clean up, So as to avoid memory leaks.\n\n# Thanks\n\nThe internal model `internal/g` is from other repos, mainly two functions:\n\n+ `G()`, from https://github.com/huandu/go-tls\n+ `G0()`, from https://github.com/timandy/routine\n\n# License\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-eden%2Froutine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgo-eden%2Froutine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-eden%2Froutine/lists"}