示例
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")
}