Collect concurrent errors with Group
Concurrently Collecting Errors with a Group
When you need to run multiple independent operations concurrently, you also need a strategy for managing their completion and collecting any errors they produce. The go-multierror package provides multierror.Group for this purpose. It allows you to launch several functions, each in its own goroutine, and then wait for them all to finish while gathering any errors that occurred.
To use it, you create a multierror.Group and then call its Go method for each function you want to execute. The Go method takes a function that returns an error and runs it in a new goroutine. After scheduling all your functions, you call the Wait method. Wait blocks until every function has completed.
If all the functions execute successfully and return nil, Wait also returns nil. This indicates that the entire group of operations completed without any errors.
package main
import (
"sync/atomic"
"github.com/hashicorp/go-multierror"
)
func main() {
var group multierror.Group
var ran atomic.Int32
group.Go(func() error { ran.Add(1); return nil })
group.Go(func() error { ran.Add(1); return nil })
result := group.Wait()
if result != nil || ran.Load() != 2 {
panic("expected both functions and no errors")
}
}
If any of the functions return an error, Wait collects them. When all functions are finished, Wait returns a non-nil error value containing the collected errors. You can check if the result is nil to determine if any operation failed.
The Group ensures that it waits for all scheduled goroutines to finish, even if some of them return errors. The order of execution and the order in which errors are collected are not guaranteed.
package main
import (
"errors"
"sync/atomic"
"github.com/hashicorp/go-multierror"
)
func main() {
var group multierror.Group
var ran atomic.Int32
group.Go(func() error { ran.Add(1); return errors.New("alpha") })
group.Go(func() error { ran.Add(1); return errors.New("beta") })
result := group.Wait()
if result == nil || ran.Load() != 2 {
panic("expected both functions and errors")
}
}