【发布时间】:2021-03-03 01:02:20
【问题描述】:
盯着一个运行递归函数的 goroutine,我想发送一个信号来停止这些递归函数。这是功能(功能不重要):
func RecursiveFunc(x int, depth int, quit chan bool) int {
if depth == 0 {
return 1
}
if quit != nil {
select {
case <-quit:
return 0
default:
}
}
total := 0
for i := 0; i < x; i++ {
y := RecursiveFunc(x, depth - 1, quit)
if y > 0 {
total += y
}
}
return total
}
这个函数可能需要很长时间才能完成,我想在发送退出信号后停止它并使用结果(不管它是什么)。运行它:
import (
"fmt"
"time"
"sync"
)
func main() {
quit := make(chan bool)
wg := &sync.WaitGroup{}
result := -1
go func() {
defer wg.Done()
wg.Add(1)
result = RecursiveFunc(5, 20, quit)
}()
time.Sleep(10 * time.Millisecond)
close(quit) // Using `quit <- true` doesn't work
wg.Wait()
fmt.Println(result)
}
为了停止 goroutine,我使用了一个通道,比如 quit,关闭它后,程序运行良好,但是我不想真正关闭通道,我只想发送一个信号 quit <- true。但是,quit <- true 不起作用,我可能只退出了一个递归实例。
如何通过发送退出信号来停止递归函数的所有实例?
【问题讨论】:
-
在 Go 中,我们有 context.Context 来创建依赖 goroutine 的层次结构;见stackoverflow.com/questions/42516717/how-to-stop-goroutine/…
-
为什么不想关闭频道?这是您描述的最简单的方法,因此最好知道您还有哪些其他限制。
-
如果您使用单个通道,您将停止应用程序中的所有 goroutine。或者,如果您想为此特定目的使用频道,则必须手动管理它们。如果你只需要在你的应用程序中停止一部分活动的 goroutines,你会怎么做?此外,使用
context.Context是 Go 中管理 goroutine 的惯用模式。 -
@djd:想象一下调用方处于一个循环中,每次迭代后我需要重用频道,我该如何重新打开频道?
-
@deepmax:只需为每个循环创建一个新频道。这是一个廉价的操作,你需要做类似的事情。基本上,使用这种方法,每个唯一通道代表一组将立即取消的 goroutines/函数调用。