示例
package main
import (
"log"
"sync"
"time"
)
func main() {
//WaitGroup让主goroutine等待所有其他goroutine
//终止。但是,这在Go中并不隐含。WaitGroup必须
//在执行任何goroutine之前显式地增加
//(即在`go`关键字之前),并且必须通过调用将其递减
//wg.Done()在每个goroutine的结尾(通常通过`defer`关键字)。
wg := sync.WaitGroup{}
//停止通道是一个无缓冲通道,当主通道关闭时
//线程希望所有其他goroutine终止(无法执行
//中断Go中的另一个goroutine)。每个goroutine必须多路复用其
//与停止频道一起工作,以确保生气勃勃。
stopCh := make(chan struct{})
for i := 0; i < 5; i++ {
//在开始之前,增加WaitGroup是很重要的
//goroutine(而不是在goroutine中),因为调度程序
//不保证goroutine在开始之前开始执行
//主goroutine调用wg.Wait()。
wg.Add(1)
go func(i int, stopCh <-chan struct{}) {
//关键字defer保证WaitGroup计数为
//当goroutine退出时递减。
defer wg.Done()
log.Printf("started goroutine %d", i)
select {
//由于我们从未在该通道上发送空结构,因此我们可以
//用通道上的接收返回来表示
//通道已关闭(记得接收永不阻塞
//封闭频道)。
case <-stopCh:
log.Printf("stopped goroutine %d", i)
}
}(i, stopCh)
}
time.Sleep(time.Second * 5)
close(stopCh)
log.Printf("stopping goroutines")
wg.Wait()
log.Printf("all goroutines stopped")
}