当主功能结束时,Go程序结束。
从语言规范
程序执行首先初始化主程序包,然后调用函数main。当该函数调用返回时,程序退出。它不等待其他(非主)goroutine完成。
因此,您需要等待goroutine完成。常见的解决方案是使用sync.WaitGroup对象。
最简单的同步goroutine的代码:
package mainimport "fmt"import "sync"var wg sync.WaitGroup // 1func routine() { defer wg.Done() // 3 fmt.Println("routine finished")}func main() { wg.Add(1) // 2 go routine() // * wg.Wait() // 4 fmt.Println("main finished")}并用于同步多个goroutine
package mainimport "fmt"import "sync"var wg sync.WaitGroup // 1func routine(i int) { defer wg.Done() // 3 fmt.Printf("routine %v finishedn", i)}func main() { for i := 0; i < 10; i++ { wg.Add(1) // 2 go routine(i) // * } wg.Wait() // 4 fmt.Println("main finished")}WaitGroup按执行顺序使用。
- 声明全局变量。使它全局化是使其对所有功能和方法可见的最简单方法。
- 增加柜台。这必须在主goroutine中完成,因为由于内存模型的保证,不能保证新启动的goroutine将在4之前执行。
- 减少计数器。这必须在goroutine的出口处完成。使用延迟调用,我们确保无论函数结束如何结束,只要函数结束,都将调用它。
- 等待计数器达到0。必须在主goroutine中执行此操作,以防止程序退出。
*实际参数在开始新的鱼肉素之前要进行评估。因此,需要在对它们进行显式评估之前,
wg.Add(1)使可能出现恐慌的代码不会留下增加的计数器。
用
param := f(x)wg.Add(1)go g(param)
代替
wg.Add(1)go g(f(x))



