Home >Backend Development >Golang >How Can I Control the Execution Order of Goroutines in Go?
Understanding Goroutine Execution Order
In a goroutine-based program, the order of execution of goroutines can be unpredictable. This is because goroutines are executed concurrently, and there's no guarantee when or in what order they will complete their tasks.
Consider the following code snippet:
func sum(a []int, c chan int) { fmt.Println("summing: ", a) total := 0 for _, v := range a { total += v } c <- total // send total to c } func main() { c := make(chan int) go sum([]int{1,2,3}, c) go sum([]int{4,5,6}, c) x := <-c fmt.Println(x) x = <-c fmt.Println(x) }
In this example, two goroutines are launched to calculate the sums of two integer slices. However, the order in which they are executed and their results are printed is not deterministic. You may observe the output as:
summing: [4 5 6] 15 summing: [1 2 3] 6
or
summing: [1 2 3] 6 summing: [4 5 6] 15
To synchronize the execution order of goroutines, various approaches can be employed:
Using Blocking Channels:
By using the blocking nature of channels, you can force the main goroutine to wait for the completion of each goroutine before moving on to the next. For instance:
func main() { c := make(chan int) go sum([]int{1, 2, 3}, c) // Blocks until a value is received x := <-c fmt.Println(x) // Execute the next goroutine go sum([]int{4, 5, 6}, c) x = <-c fmt.Println(x) }
Using Wait Groups:
Another common synchronization technique involves using wait groups. A wait group keeps track of the number of goroutines that are still running and waits for them all to complete before proceeding further. Here's how you can use a wait group in the example above:
func sum(a []int, c chan int, wg *sync.WaitGroup) { defer wg.Done() fmt.Println("summing: ", a) total := 0 for _, v := range a { total += v } c <- total // send total to c } func main() { c := make(chan int) wg := new(sync.WaitGroup) // Increment the wait group wg.Add(1) // Launch the first goroutine go sum([]int{1, 2, 3}, c, wg) // Wait for the first goroutine to complete wg.Wait() // Increment the wait group again wg.Add(1) // Launch the second goroutine go sum([]int{4, 5, 6}, c, wg) // Wait for the second goroutine to complete wg.Wait() // Close the channel to indicate that no more values will be sent close(c) // Range over the channel to receive the results for theSum := range c { x := theSum fmt.Println(x) } }
By incorporating synchronization techniques into your code, you gain greater control over the order in which goroutines execute, ensuring that they complete their tasks in the desired sequence.
The above is the detailed content of How Can I Control the Execution Order of Goroutines in Go?. For more information, please follow other related articles on the PHP Chinese website!