我需要调用一个将 Context
作为参数的函数。此代码块可以访问 channel ,该 channel 用于发信号通知应取消操作。
这是接收值时我当前用来取消Context
的内容:
func doSomething(stop <-chan bool) {
ctx, cancel := context.WithCancel(context.Background())
go func() {
select {
case <-ctx.Done():
case <-stop:
cancel()
}
}()
longRunningFunction(ctx)
}
预期的控制流程如下:
<-ctx.Done()
将触发,goroutine将终止。 stop
上接收到一个值,则上下文将被取消,并通知任务它应该退出。再次,goroutine将在发生这种情况时终止。 这似乎过于复杂。有没有更简单的方法来完成预期的行为?
最佳答案
正如@ain所提到的,如果longRunningFunction
运行到末尾,并且stop
上没有发送任何内容(或未关闭),则您的代码当前会泄漏goroutine:select
语句将永远无法实现(完成context
的唯一方法是当stop
中出现某些内容时,调用cancel
)。
这是修复它的一种方法(主要是@ain's comment的实现):
func doSomething(stop <-chan bool) {
ctx := context.TODO() // because in the future, you might pass a ctx arg to this function, from which you could then "inherit"
ctx, cancel := context.WithCancel(ctx)
defer cancel() // to be sure to release the associated resources whatever happens (and prevent the following goroutine from leaking)
go func() {
select {
case <-ctx.Done():
case <-stop:
cancel()
}
}()
longRunningFunction(ctx)
}
关于go - 有没有更简洁的方法来创建在 channel 上接收后被取消的上下文?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43434939/