func getRecords(ctx context.Context, ids *[]Id) error {
ctx, cancel := context.WithTimeout(ctx, DefaultTimeout)
defer cancel()
var wg sync.WaitGroup
size := len(*ids)
allErrors := make(chan error, size)
for i := 0; i < size; i++ {
wg.Add(1)
go func(x int){
err := //call to other func which return error type. nil or error
if err != nil { // I will be creating n goroutines. How to exit rightaway if one of
// them return error
allErrors <- err
}
wg.Done()
}(i)
}
go func() {
wg.Wait()
close(allErrors)
}
return nil
}
How to exit on the anonymous function here?
You need to use ErrGroup
This is what ErrGroup.Go Does
The first call to return a non-nil error cancels the group; its error will be returned by Wait.
So the other goroutines will be automatically canceled when any one of the goroutine return error.
Usage:
errs, ctx = errgroup.WithContext(ctx)
for i := 0; i < size; i++ {
errs.Go( func() error{
...
})
}
if err := g.Wait(); err != nil {
// Handle Errors from GoRoutines
}
Edit:
Maybe the answer was not descriptive enough. when the docs say other goroutines will be canceled, it means the context
that was returned by errGroup
will be issued a cancelation. So each go routine owner must handle this cancelation in their code.
Example: https://go.dev/play/p/hXWjtN4uj06
Real World Example: When your golang service starts, maybe you start a HTTP server in one routine, a Kafka consumer in another and say a grpc server in the last one. Now if any one of them stops, you want to stop the whole service (consider the service being down). Then you share the errGroupd context with all these goroutines (Luckily these underlying services already handle this context cancelation logic, so you don't have to write one) but if that goroutine does something custom then its the goroutine owner's responsibility to handle cancelation signal