sync.WaitGroup可以使得我们很优雅的等待协程的退出
写一个普通的例子。下面的例子中,say函数中的字符串不会输出,因为main函数也是一个协程,say函数相当于一个子协程,父协程运行完退出后,子协程也会退出,并不会等待子协程中的任务完成,而要想执行完子协程中的任务,最简单的方法是让父协程等待一段时间,子协程可以在这段时间内执行完任务。去掉下面的注释后,say函数就可以执行完内部的任务。
package main
import (
"fmt"
"time"
)
func say() {
fmt.Println("hello world")
}
func main() {
for i := 0; i < 10; i++ {
go say()
}
fmt.Println("I Love You")
// time.Sleep(time.Second) // 去掉注释
}
但是,我们并不知道子协程要执行多长时间,当执行I/O操作时,我们无法确保准确的时间,所以以上的方法不能用于正常的逻辑中。
(wg * WaitGroup) Add(delta int)(wg *WaitGroup) Done()(wg *WaitGroup) Wait()
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup // 定义全局的结构体变量
func say() {
defer wg.Done() // 计数器 -1
fmt.Println("hello world")
}
func main() {
wg.Add(5) // 计数器为5
for i := 0; i < 5; i++ {
go say()
}
fmt.Println("I Love You")
wg.Wait() // 阻塞父协程
fmt.Println("I Love You")
}
/* 结果
I Love You
hello world
hello world
hello world
hello world
hello world
I Love You
*/