« Back to Index

Go: errgroup

View original Gist on GitHub

Tags: #go #concurrency #errors

errgroup.md

[!TIP] For a real-world example see this gist.

errgroup.Group in Go is a great way to manage concurrent goroutines that return errors. It simplifies error handling and ensures that all goroutines finish or exit if any one of them fails. However, there are specific scenarios where it shines and others where it might not be the best fit.

When to use errgroup.Group

  1. Multiple Independent Goroutines:
    If you need to launch several goroutines concurrently, and each one performs an independent task (like querying different services), errgroup helps manage their lifecycle.
  2. Error-First Cancellation:
    When any goroutine’s error should cancel all other goroutines, errgroup simplifies this with context cancellation. It ensures that if one task fails, the others stop as soon as possible.
  3. Resource Cleanup:
    If goroutines hold resources (e.g., database connections or files), errgroup ensures that when one fails, the others can clean up or abort gracefully.
  4. Waiting for All Goroutines:
    errgroup provides a simple way to wait for all goroutines to finish without manually tracking them. It reduces boilerplate code by calling g.Wait().
  5. Hierarchical Task Execution:
    If tasks spawn subtasks, errgroup can manage goroutines at multiple levels with different cancellation contexts.

When NOT to use errgroup.Group

  1. Fire-and-Forget Goroutines:
    If the goroutines don’t return errors and don’t need to be canceled on failure, using errgroup adds unnecessary complexity. Just use sync.WaitGroup instead.
  2. Tight Loops with Many Goroutines:
    For creating a large number of goroutines (like in a loop), errgroup may not be ideal because it cancels all goroutines on the first error, potentially leaving work unfinished.
  3. Performance-Critical Sections:
    errgroup uses context.WithCancel internally, which introduces a slight overhead. In extremely performance-sensitive scenarios, using sync.WaitGroup might be more efficient.
  4. Tasks Without Shared Context:
    If the tasks do not depend on a shared context or don’t need coordinated cancellation, errgroup is overkill.
  5. Partial Completion is Acceptable:
    If some goroutines can fail without affecting the outcome of the program, you might prefer sync.WaitGroup or custom error aggregation rather than stopping all work at the first failure.