Golang Simultaneous Processing With Cancellation
A demo showing how to run processes simultaneously using wait groups, but where the whole process cancels if one operation encounters an error.
Check it out here: Demo Link
package main import ( "fmt" "sync" ) func main() { DoAsyncOps() /* * This will execute three operations in parallel. Here's a sample output: * Starting async operations * third * second * first * * Or in the case of an error: * Starting async operations * first * Issue running async operations */ } func PrintStuff(stuff string) error { _, err := fmt.Println(stuff) //Uncomment the following code to test an error case /*if stuff == "first" { return fmt.Errorf("error happened here: %s", stuff) }*/ return err } func DoAsyncOps() error { wg := new(sync.WaitGroup) wg.Add(3) errChannel := make(chan error, 1) finished := make(chan bool, 1) fmt.Println("Starting async operations") /* * Run the operation you want to run in a goroutine which marks the operation as finished when the * operation is done or pushes an error to the error channel */ go func() { defer wg.Done() if err := PrintStuff("first"); err != nil { errChannel <- err } }() go func() { defer wg.Done() if err := PrintStuff("second"); err != nil { errChannel <- err } }() go func() { defer wg.Done() if err := PrintStuff("third"); err != nil { errChannel <- err } }() /* * Wait for the goroutines to finish in another goroutine which then indicates that we're done using * the finished channel */ go func() { wg.Wait() close(finished) }() /* * Quit if the `finished` channel is or if we receive an error through the error channel */ select { case <-finished: case err := <-errChannel: if err != nil { fmt.Println("Issue running async operations") return err } } return nil }

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
Download this code in plain text format here