Golang 中的取消模式
Cancellation pattern in Golang
引用自50 Shades Of Go: Traps, Gotchas and Common mistakes:
You can also use a special cancellation channel to interrupt the
workers.
func First(query string, replicas ...Search) Result {
c := make(chan Result)
done := make(chan struct{})
defer close(done)
searchReplica := func(i int) {
select {
case c <- replicas[i](query):
case <- done:
}
}
for i := range replicas {
go searchReplica(i)
}
return <-c
}
据了解,这意味着我们使用通道done
提前中断worker,而不是等待完全执行(在我们的例子中执行replicas[i](query)
。因此,我们可以接收最快工人 ("First Wins Pattern") 的结果,然后取消所有其他工人的工作并节省资源。
另一方面,根据 specification:
For all the cases in the statement, the channel operands of receive
operations and the channel and right-hand-side expressions of send
statements are evaluated exactly once, in source order, upon entering
the "select" statement.
据我了解,这意味着我们不能interrupt the workers
,因为在任何情况下,所有工作人员都会评估函数replicas[i]query
,然后才select case <- done
和完成他们的执行。
能否请您指出我推理中的错误?
你的推理是正确的,网站上的措辞并不完全清楚。这个 "construct" 实现的是 goroutines 不会永远挂起,但是一旦搜索完成,goroutines 就会正常结束。那里什么也没有发生。
一般来说,你不能从外部中断任何 goroutine,goroutine 本身必须支持某种终止(例如关闭通道,context.Context
等)。参见 。
所以是的,在您发布的示例中,将同时启动所有搜索,最快的结果将在到达时返回,其余 goroutine 将继续 运行 只要他们的搜索已经完成。
剩下的怎么办?其余的将被丢弃(case <- done
将被选中,因为无缓冲通道不能容纳任何元素,并且不会有其他人从该通道接收更多元素)。
你可以在这个Go Playground example中验证这一点。
引用自50 Shades Of Go: Traps, Gotchas and Common mistakes:
You can also use a special cancellation channel to interrupt the workers.
func First(query string, replicas ...Search) Result {
c := make(chan Result)
done := make(chan struct{})
defer close(done)
searchReplica := func(i int) {
select {
case c <- replicas[i](query):
case <- done:
}
}
for i := range replicas {
go searchReplica(i)
}
return <-c
}
据了解,这意味着我们使用通道done
提前中断worker,而不是等待完全执行(在我们的例子中执行replicas[i](query)
。因此,我们可以接收最快工人 ("First Wins Pattern") 的结果,然后取消所有其他工人的工作并节省资源。
另一方面,根据 specification:
For all the cases in the statement, the channel operands of receive operations and the channel and right-hand-side expressions of send statements are evaluated exactly once, in source order, upon entering the "select" statement.
据我了解,这意味着我们不能interrupt the workers
,因为在任何情况下,所有工作人员都会评估函数replicas[i]query
,然后才select case <- done
和完成他们的执行。
能否请您指出我推理中的错误?
你的推理是正确的,网站上的措辞并不完全清楚。这个 "construct" 实现的是 goroutines 不会永远挂起,但是一旦搜索完成,goroutines 就会正常结束。那里什么也没有发生。
一般来说,你不能从外部中断任何 goroutine,goroutine 本身必须支持某种终止(例如关闭通道,context.Context
等)。参见
所以是的,在您发布的示例中,将同时启动所有搜索,最快的结果将在到达时返回,其余 goroutine 将继续 运行 只要他们的搜索已经完成。
剩下的怎么办?其余的将被丢弃(case <- done
将被选中,因为无缓冲通道不能容纳任何元素,并且不会有其他人从该通道接收更多元素)。
你可以在这个Go Playground example中验证这一点。