Idiomatic Goroutine Termination and Error Handling: A Case Study
In Go, handling goroutine termination is often a challenge for developers. One common issue is ensuring proper cleanup of goroutines when an error occurs. This article demonstrates an elegant and idiomatic solution to this problem using error grouping.
Consider the following example:
package main import ( "sync" "time" ) func fetchAll() error { wg := sync.WaitGroup{} errs := make(chan error) // run all the http requests in parallel for i := 0; i < 4; i++ { wg.Add(1) go func(i int) { defer wg.Done() // pretend this does an http request and returns an error time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) errs <- fmt.Errorf("goroutine %d's error returned", i) }(i) } // wait until all the fetches are done and close the error // channel so the loop below terminates go func() { wg.Wait() close(errs) }() // return the first error for err := range errs { if err != nil { return err } } return nil }
This implementation has a critical flaw: it leaks goroutines. The fix is to use an error group:
package main import ( "context" "fmt" "math/rand" "time" "golang.org/x/sync/errgroup" ) func fetchAll(ctx context.Context) error { errs, ctx := errgroup.WithContext(ctx) // run all the http requests in parallel for i := 0; i < 4; i++ { errs.Go(func() error { // pretend this does an http request and returns an error time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) return fmt.Errorf("error in go routine, bailing") }) } // Wait for completion and return the first error (if any) return errs.Wait() }
An error group automatically waits for all goroutines to complete successfully or cancels those remaining in case of an error. In the above case, the first goroutine that encounters an error triggers cancellation of all others, and the error is propagated back to the caller. The use of context ensures graceful termination when the surrounding context is canceled.
The above is the detailed content of How to Gracefully Terminate Goroutines and Handle Errors in Go?. For more information, please follow other related articles on the PHP Chinese website!