3 回答
TA贡献1772条经验 获得超8个赞
Go 程序在 main 函数结束时结束。
从语言规范
程序执行首先初始化主包,然后调用函数 main。当该函数调用返回时,程序退出。它不会等待其他(非主)goroutine 完成。
因此,您需要等待 goroutine 完成。对此的常见解决方案是使用sync.WaitGroup对象。
最简单的同步 goroutine 的代码:
package main
import "fmt"
import "sync"
var wg sync.WaitGroup // 1
func 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 main
import "fmt"
import "sync"
var wg sync.WaitGroup // 1
func routine(i int) {
defer wg.Done() // 3
fmt.Printf("routine %v finished\n", i)
}
func main() {
for i := 0; i < 10; i++ {
wg.Add(1) // 2
go routine(i) // *
}
wg.Wait() // 4
fmt.Println("main finished")
}
WaitGroup 按执行顺序使用。
全局变量的声明。使其全局化是使其对所有函数和方法可见的最简单方法。
增加计数器。这必须在 main goroutine 中完成,因为由于内存模型保证,不能保证新启动的 goroutine 会在 4 之前执行。
减少计数器。这必须在 goroutine 退出时完成。使用延迟调用,我们确保无论何时函数结束,无论它如何结束,它都会被调用。
等待计数器达到 0。这必须在 main goroutine 中完成以防止程序退出。
*在启动新 gouroutine 之前评估实际参数。因此需要在之前明确评估它们,wg.Add(1)
以便可能出现恐慌的代码不会留下增加的计数器。
用
param := f(x)
wg.Add(1)
go g(param)
代替
wg.Add(1)
go g(f(x))
- 3 回答
- 0 关注
- 558 浏览
添加回答
举报