等待 goroutines

main 函数结束时程序结束 ,因此通常的做法是等待所有 goroutine 完成。一个常见的解决方案是使用 sync.WaitGroup对象。

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup // 1

func routine(i int) {
    defer wg.Done() // 3
    fmt.Printf("routine %v finished\n", i)
}

func main() {
    wg.Add(10) // 2
    for i := 0; i < 10; i++ {
        go routine(i) // *
    }
    wg.Wait() // 4
    fmt.Println("main finished")
}

在操场上运行示例

WaitGroup 按执行顺序使用:

  1. 全局变量声明。使其全局化是使其对所有函数和方法可见的最简单方法。
  2. 增加柜台。这必须在主 goroutine 中完成,因为由于内存模型保证, 无法保证新启动的 goroutine 将在 4 之前执行。
  3. 减少柜台。这必须在 goroutine 的出口处完成。通过使用延迟调用,我们确保无论函数如何结束都会在函数结束时调用它。
  4. 等待计数器达到 0.这必须在主 goroutine 中完成,以防止程序在所有 goroutine 完成之前退出。

* 在开始新的 goroutine 之前评估参数。因此,有必要在 wg.Add(10) 之前明确定义它们的值,以便可能恐慌的代码不会增加计数器。向 WaitGroup 添加 10 个项目,因此它将等待 10 个项目,然后 wg.Wait 将控制权返回给 main() goroutine。这里,i 的值在 for 循环中定义。