3 回答
TA贡献1936条经验 获得超6个赞
Go的当前运行时设计假定程序员负责检测何时终止goroutine和何时终止程序。程序员需要计算goroutine以及整个程序的终止条件。可以通过调用os.Exit或从main()函数返回以正常方式终止程序。
main()通过立即在所述通道上接收来创建通道并延迟退出,是一种防止main退出的有效方法。但是它不能解决检测何时终止程序的问题。
如果在main()函数进入等待所有goroutines终止循环之前无法计算goroutine的数量,则需要发送增量,以便main函数可以跟踪正在运行的goroutine的数量:
// Receives the change in the number of goroutines
var goroutineDelta = make(chan int)
func main() {
go forever()
numGoroutines := 0
for diff := range goroutineDelta {
numGoroutines += diff
if numGoroutines == 0 { os.Exit(0) }
}
}
// Conceptual code
func forever() {
for {
if needToCreateANewGoroutine {
// Make sure to do this before "go f()", not within f()
goroutineDelta <- +1
go f()
}
}
}
func f() {
// When the termination condition for this goroutine is detected, do:
goroutineDelta <- -1
}
另一种方法是将频道替换为sync.WaitGroup。这种方法的缺点是wg.Add(int)需要在调用之前先进行调用wg.Wait(),因此必须在其中至少创建一个goroutine,main()然后才能在程序的任何部分中创建后续goroutine:
var wg sync.WaitGroup
func main() {
// Create at least 1 goroutine
wg.Add(1)
go f()
go forever()
wg.Wait()
}
// Conceptual code
func forever() {
for {
if needToCreateANewGoroutine {
wg.Add(1)
go f()
}
}
}
func f() {
// When the termination condition for this goroutine is detected, do:
wg.Done()
}
TA贡献1909条经验 获得超7个赞
Go的运行时程序包具有一个名为的函数runtime.Goexit,该函数可以完全满足您的要求。
从主goroutine调用Goexit会终止该goroutine,而不会返回func main。由于func main尚未返回,因此程序将继续执行其他goroutine。如果所有其他goroutine退出,程序将崩溃。
在操场上的例子
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
go func() {
time.Sleep(time.Second)
fmt.Println("Go 1")
}()
go func() {
time.Sleep(time.Second * 2)
fmt.Println("Go 2")
}()
runtime.Goexit()
fmt.Println("Exit")
}
- 3 回答
- 0 关注
- 376 浏览
添加回答
举报