{"id":20979019,"url":"https://github.com/1pkg/golatch","last_synced_at":"2026-05-17T21:36:10.648Z","repository":{"id":144227147,"uuid":"314314888","full_name":"1pkg/golatch","owner":"1pkg","description":"Golatch 🔒 seamlessly patches go runtime to provide a way to overwrite empty value returned from closed channel.","archived":false,"fork":false,"pushed_at":"2024-04-21T21:58:20.000Z","size":169,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-31T11:28:08.577Z","etag":null,"topics":["chan","channel","close","go","golang"],"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/1pkg.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":"2020-11-19T17:02:46.000Z","updated_at":"2024-04-21T21:56:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"ef974504-0e8d-46f7-8b9c-9ae8720fe296","html_url":"https://github.com/1pkg/golatch","commit_stats":null,"previous_names":["1pkg/golock","1pkg/go2close"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/1pkg/golatch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1pkg%2Fgolatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1pkg%2Fgolatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1pkg%2Fgolatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1pkg%2Fgolatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/1pkg","download_url":"https://codeload.github.com/1pkg/golatch/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1pkg%2Fgolatch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33155861,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T09:28:26.183Z","status":"ssl_error","status_checked_at":"2026-05-17T09:27:52.702Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["chan","channel","close","go","golang"],"created_at":"2024-11-19T05:10:34.111Z","updated_at":"2026-05-17T21:36:10.622Z","avatar_url":"https://github.com/1pkg.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Golatch 🔒\n\n[![lint](https://github.com/1pkg/golatch/workflows/lint/badge.svg)](https://github.com/1pkg/golatch/actions?query=workflow%3Alint+branch%3Amaster+)\n[![test](https://github.com/1pkg/golatch/workflows/test/badge.svg)](https://github.com/1pkg/golatch/actions?query=workflow%3Atest+branch%3Amaster+)\n[![report](https://goreportcard.com/badge/github.com/1pkg/golatch?cache=false)](https://goreportcard.com/report/github.com/1pkg/golatch)\n[![version](https://img.shields.io/github/go-mod/go-version/1pkg/golatch)](https://github.com/1pkg/golatch/blob/master/go.mod)\n[![license](https://img.shields.io/github/license/1pkg/golatch?cache=false)](LICENSE)\n[![godoc](https://img.shields.io/badge/godoc-godoc-green)](https://pkg.go.dev/github.com/1pkg/golatch?tab=doc)\n\n`go get -u github.com/1pkg/golatch`\n\n[blog post article](https://1pkg.github.io/posts/lets_make_closed_channels_more_useful/)\n\n## Introduction\n\nGolatch seamlessly patches go runtime to provide a way to close a chan idempotently + overwrite empty value returned from that closed channel.\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003cth\u003eWith Golatch\u003c/th\u003e\n\u003cth\u003eWithout Golatch\u003c/th\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003e\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n\n\t\"github.com/1pkg/golatch\"\n)\n\nfunc main() {\n\tch := make(chan int)\n\tvar wg sync.WaitGroup\n\twg.Add(5)\n\tfor i := 0; i \u003c 5; i++ {\n\t\tgo worker(i, ch, \u0026wg)\n\t}\n\tgolatch.Close(ch, 10)\n\twg.Wait()\n}\n\nfunc worker(i int, ch chan int, wg *sync.WaitGroup) {\n\tv, ok := \u003c- ch // 10, false\n\tif ok || v != 10 {\n\t\tpanic(\"unreachable\") // won't panic\n\t}\n\tfmt.Printf(\"worker %d chan is closed with value %d\\n\", i, v)\n\twg.Done()\n}\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n)\n\nfunc main() {\n\tch := make(chan int)\n\tvar wg sync.WaitGroup\n\twg.Add(5)\n\tfor i := 0; i \u003c 5; i++ {\n\t\tgo worker(i, ch, \u0026wg)\n\t}\n\tclose(ch)\n\twg.Wait()\n}\n\nfunc worker(i int, ch chan int, wg *sync.WaitGroup) {\n\tv, ok := \u003c- ch // 0, false\n\tif ok || v != 10 {\n\t\tpanic(\"unreachable\") // will panic\n\t}\n\tfmt.Printf(\"worker %d chan is closed with value %d\\n\", i, v)\n\twg.Done()\n}\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n## Internals\n\nGolatch exposes single function `Close` that idempotently closes provided chan and stores provided value to return as this channel closed value instead of empty value. If provided channel is not a writable channel `NotWritableChannel` error is returned. If provided value doesn't match underlying channel type `ChannelTypeMismatch` error is returned.  \nTo cancel the effect of closed value replace call cancel function. Note that provided value won't be automatically collected by GC together with provided channel to remove provided value from the storage call cancel function. Note that after cancelation is called next call to `Close` will cause a panic `close of closed channel`. Note that unless cancelation is called next call to `Close` is safe and won't cause any panic but just update storage value with new provided value. Note that in order to achieve such effect golatch uses package based on [bou.ke/monkey](https://github.com/bouk/monkey) to patch all existing channel receive entrypoints:\n\n- direct chan receive\n- chan select statement\n- reflect chan receive\n\nThis makes golatch inherits the same list of restrictions as `bou.ke/monkey` [has](https://github.com/bouk/monkey#notes). Note that multiselect statement is patched via patch guard, which makes it not thread safe.\n\n## Licence\n\nGolatch is licensed under the MIT License.  \nSee [LICENSE](LICENSE) for the full license text.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F1pkg%2Fgolatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F1pkg%2Fgolatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F1pkg%2Fgolatch/lists"}