看看这个人为的例子:
package main
import "fmt"
func printElo() {
fmt.Printf("Elo\n")
}
func printHello() {
fmt.Printf("Hello\n")
}
func main() {
fmt.Printf("This will print.")
i := 0
for i < 10 {
go printElo()
go printHello()
i++
}
}
该程序的输出将只是“这将打印”。 goroutines printElo()
和 printHello
的输出不会被发出,因为我猜 main()
函数线程将在 goroutines 完成之前完成甚至有机会开始执行。
让类似代码在 Golang 中工作并且不会过早终止的惯用方法是什么?
最佳答案
最简单、最干净和“可扩展”的方法是使用 sync.WaitGroup
:
var wg = &sync.WaitGroup{}
func printElo() {
defer wg.Done()
fmt.Printf("Elo\n")
}
func printHello() {
defer wg.Done()
fmt.Printf("Hello\n")
}
func main() {
fmt.Printf("This will print.")
i := 0
for i < 10 {
wg.Add(1)
go printElo()
wg.Add(1)
go printHello()
i++
}
wg.Wait()
}
输出(在 Go Playground 上尝试):
This will print.Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
使用 sync.WaitGroup
时要遵循的简单“规则”:
- 调用
WaitGroup.Add()
在go
之前的“原始”goroutine(开始一个新的)中声明 - 建议调用
WaitGroup.Done()
延迟,因此即使 goroutine 发生 panic ,它也会被调用 - 如果您想将
WaitGroup
传递给其他函数(并且不使用包级变量),则必须传递一个指向它的指针,否则WaitGroup
(即a struct) 将被复制,并且在副本上调用的Done()
方法不会在原始对象上观察到
关于go - 防止 main() 函数在 Goroutine 在 Golang 中完成之前终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42752705/