{"id":16895986,"url":"https://github.com/stevenacoffman/errgroup","last_synced_at":"2025-04-11T06:30:42.789Z","repository":{"id":57584030,"uuid":"330000324","full_name":"StevenACoffman/errgroup","owner":"StevenACoffman","description":"Drop in replacement for errgroup that converts panics to errors","archived":false,"fork":false,"pushed_at":"2021-01-15T22:13:29.000Z","size":10,"stargazers_count":15,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-10T16:23:15.574Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/StevenACoffman.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":"2021-01-15T19:11:48.000Z","updated_at":"2024-12-04T10:04:18.000Z","dependencies_parsed_at":"2022-09-10T09:00:29.647Z","dependency_job_id":null,"html_url":"https://github.com/StevenACoffman/errgroup","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/StevenACoffman%2Ferrgroup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StevenACoffman%2Ferrgroup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StevenACoffman%2Ferrgroup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StevenACoffman%2Ferrgroup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/StevenACoffman","download_url":"https://codeload.github.com/StevenACoffman/errgroup/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248355414,"owners_count":21090009,"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":[],"created_at":"2024-10-13T17:27:17.008Z","updated_at":"2025-04-11T06:30:42.530Z","avatar_url":"https://github.com/StevenACoffman.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Actions Status](https://github.com/neilotoole/errgroup/workflows/Go/badge.svg)](https://github.com/neilotoole/errgroup/actions?query=workflow%3AGo)\n[![Go Report Card](https://goreportcard.com/badge/StevenACoffman/errgroup)](https://goreportcard.com/report/StevenACoffman/errgroup)\n[![GoDoc](https://godoc.org/github.com/golang/gddo?status.svg)](https://pkg.go.dev/github.com/StevenACoffman/errgroup)\n[![license](https://img.shields.io/github/license/StevenACoffman/errgroup)](./LICENSE)\n\n# StevenACoffman/errgroup\n`StevenACoffman/errgroup` is a drop-in alternative to Go's wonderful\n[`sync/errgroup`](https://pkg.go.dev/golang.org/x/sync/errgroup) but it converts goroutine panics to errors. \n\nWhile `net/http` installs a panic handler with each request-serving goroutine,\ngoroutines **do not** and **cannot** inherit panic handlers from parent goroutines,\nso a `panic()` in one of the child goroutines will kill the whole program.\n\nSo whenever you use an `sync.errgroup`, with some discipline, you can always remember to add a\ndeferred `recover()` to every goroutine.  This library just avoids that boilerplate and does that for you.\n\nYou can [see it in use](https://play.golang.org/p/S8Gmr_sWZIi)\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/StevenACoffman/errgroup\"\n)\n\nfunc main() {\n\tg := new(errgroup.Group)\n\tvar urls = []string{\n\t\t\"http://www.golang.org/\",\n\t\t\"http://www.google.com/\",\n\t\t\"http://www.somestupidname.com/\",\n\t}\n\tfor i := range urls {\n\t\t// Launch a goroutine to fetch the URL.\n\t\ti := i // https://golang.org/doc/faq#closures_and_goroutines\n\t\tg.Go(func() error {\n\n\t\t\t// deliberate index out of bounds triggered\n\t\t\tfmt.Println(\"Fetching:\", i, urls[i+1])\n\n\t\t\treturn nil\n\t\t})\n\t}\n\t// Wait for all HTTP fetches to complete.\n\terr := g.Wait()\n\tif err == nil {\n\t\tfmt.Println(\"Successfully fetched all URLs.\")\n\t} else {\n\t\tfmt.Println(err)\n\t}\n}\n```\n\nThis work was done by my co-worker [Ben Kraft](https://github.com/benjaminjkraft), and, with his permission, I lightly modified it to\nlift it out of our repository for Go community discussion.\n\n### Counterpoint\nThere is [an interesting discussion](https://github.com/oklog/run/issues/10) which has an alternative view that,\nwith few exceptions, panics **should** crash your program.\n\n### Prior Art\nWith only a cursory search, I found a few existing open source examples.\n\n#### [Kratos](https://github.com/go-kratos/kratos errgroup \n\nKratos Go framework for microservices has a similar [errgroup](https://github.com/go-kratos/kratos/blob/master/pkg/sync/errgroup/errgroup.go)\nsolution.\n\n#### PanicGroup by Sergey Alexandrovich\n\nIn the article [Errors in Go:\nFrom denial to acceptance](https://evilmartians.com/chronicles/errors-in-go-from-denial-to-acceptance), \n(which advocates panic based flow control 😱), they have a PanicGroup that's roughly equivalent:\n\n```\ntype PanicGroup struct {\n  wg      sync.WaitGroup\n  errOnce sync.Once\n  err     error\n}\n\nfunc (g *PanicGroup) Wait() error {\n  g.wg.Wait()\n  return g.err\n}\n\nfunc (g *PanicGroup) Go(f func()) {\n  g.wg.Add(1)\n\n  go func() {\n    defer g.wg.Done()\n    defer func(){\n      if r := recover(); r != nil {\n        if err, ok := r.(error); ok {\n          // We need only the first error, sync.Once is useful here.\n          g.errOnce.Do(func() {\n            g.err = err\n          })\n        } else {\n          panic(r)\n        }\n      }\n    }()\n\n    f()\n  }()\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstevenacoffman%2Ferrgroup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstevenacoffman%2Ferrgroup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstevenacoffman%2Ferrgroup/lists"}