This post is to introduce a type in GoLang called WaitGroup

Introduction

https://golang.org/pkg/sync/#WaitGroup

A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls Done when finished. At the same time, Wait can be used to block until all goroutines have finished.

A WaitGroup must not be copied after first use.

用人话说,WaitGroup就是用来管理很多gorountines的。它可以用来等待它管理的所有gorountines完成,只要有任何一个没有完成,就block后面程序的执行。

Methods Available

Add

func (wg *WaitGroup) Add(delta int)

delta可以是正数也可以是负数,用于更新WG背后的counter。当counter是0的时候,所有goroutines都被block住,直到Wait释放。如果counter更新成负数,程序会panic。

Done

func (wg *WaitGroup) Done()

Done将counter减去一。

Wait

func (wg *WaitGroup) Wait()

Wait等待counter为0。

怎么用呢?

抓重点,WaitGroup创建完就可以开始用了。WaitGroup并不细究哪个gorountine是哪个gorountine。WG只管多少gorountine在执行,要等待多少个完成。

当你开一个gorountine的时候,就可以Add(1)了,在gorountine完成时,你可以done()或者Add(-1)。Wait() 放在最后使用,代表gorountine已经setup好了,现在就等这一批全完成。之后可以在Add和Wait。我试了下,WaitGroup是可以重复使用。

WaitGroup in action

https://play.golang.org/p/1gYaFXTkPDi

Few more things to keep in mind

WaitGroup对象不是一个引用类型,在通过函数传值时需要使用地址

func main() {
    wg := sync.WaitGroup{}
    wg.Add(100)
    for i := 0; i < 100; i++ {
        go f(i, &wg)
    }
    wg.Wait()
}

// 一定要通过指针传值,不然进程会进入死锁状态
func f(i int, wg *sync.WaitGroup) { 
    fmt.Println(i)
    wg.Done()
}