When you actually use Go coroutines for parallel applications, you might run into scenarios where you need to block some code execution until other coroutines have successfully executed. Sample code:
package main
import "fmt"
func myFunc() {
fmt.Println("hello my goroutine")
}
func main() {
fmt.Println("Hello World")
go myFunc()
fmt.Println("main goroutine done")}
Copy the code
The results are as follows:
Hello World
main goroutine done
Copy the code
The message “Hello my Goroutine” in the coroutine does not appear. When the program starts, the Go program creates a default goroutine for the main() function. The goroutine ends when main() returns, and all goroutines started in main() end with it. The goroutine in main is like the Night King in Game of Thrones, and all other goroutines are White Walkers. When the Night King dies, all the White Walkers he turned will be destroyed. In plain English, the logic in the coroutine was not executed because main had ended before the coroutine was executed.
WaitGroups solve this problem by blocking applications until all of the coroutines in the synchronous wait group have successfully executed.
WatiGroup is a struct type in the sync package that collects goroutines that need to wait for execution to complete.
It has three methods:
- Add() : Call Add() to set or Add the number of goroutines to wait for each activation of a goroutine that you want to complete
- Such as Add(2) or both calls to Add(1) will set the wait counter to 2, meaning that two goroutines are waiting to complete
- Done() : This method should be called to artificially indicate that a goroutine is finished each time it needs to wait until it is actually Done. This method decrement the wait counter by one
- Wait() : Wait() blocks the current Goroutine until the counter is reduced to 0
So let’s change the code:
package main
import (
"fmt"
"sync"
)
func myFunc(waitgroup *sync.WaitGroup) {
fmt.Println("hello my goroutine")
waitgroup.Done()
}
func main() {
fmt.Println("Hello World")
var waitgroup sync.WaitGroup
waitgroup.Add(1)
go myFunc(&waitgroup)
waitgroup.Wait()
fmt.Println("main goroutine done")}
Copy the code
The results are as follows:
Hello World
hello my goroutine
main goroutine done
Copy the code
It is also important to note that myFunc() uses * sync.waitgroup as a pointer. We cannot use sync.waitgroup as a value because this means that each goroutine copies a WaitGroup. Each Goroutine uses its own Waitgroup. This is obviously unreasonable, and multiple Goroutines should share a WaitGroup to know that they are all finished. In fact, the main Goroutine will block permanently, resulting in a deadlock, if you use a value type parameter.
We can do the same with anonymous functions. For uncomplicated coroutine internal business, anonymous functions make the program more concise:
package main
import (
"fmt"
"sync"
)
func main() {
fmt.Println("Hello World")
var waitgroup sync.WaitGroup
waitgroup.Add(1)
go func() {
fmt.Println("hello my goroutine")
waitgroup.Done()
}()
waitgroup.Wait()
fmt.Println("main goroutine done")
}
Copy the code
Refer to the article: blog.csdn.net/neweastsun/…
www.cnblogs.com/f-ck-need-u…