这是来自50 Shades Of Go: Traps, Gotchas and Common mistakes 的引述:您还可以使用特殊的取消通道来打断工人。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提前中断工作人员而不等待完全执行(在我们的案例中执行replicas[i](query)。因此,我们可以从最快的工作人员(“First Wins Pattern”)收到结果,然后取消所有其他工人的工作并节省资源。另一方面,根据规范:对于语句中的所有情况,接收操作的通道操作数以及发送语句的通道和右侧表达式在输入“select”语句时按源顺序恰好计算一次。据我了解,这意味着我们不能interrupt the workers,因为在任何情况下,所有工作人员都会评估功能replicas[i]query,然后才选择case <- done并完成他们的执行。能否请您指出我推理中的错误?
1 回答
慕桂英3389331
TA贡献2036条经验 获得超8个赞
您的推理是正确的,网站上的措辞并不完全清楚。这个“构造”实现的是 goroutines 不会永远挂起,但是一旦搜索完成,goroutines 就会正确结束。那里什么也没有发生。
通常,您不能从外部中断任何 goroutine,goroutine 本身必须支持某种终止(例如关闭通道context.Context
等)。
所以是的,在您发布的示例中,将同时启动所有搜索,最快的搜索结果将在到达时返回,只要搜索完成,其余的 goroutine 将继续运行。
剩下的怎么办?其余的将被丢弃(case <- done
将被选中,因为无缓冲的通道不能容纳任何元素,并且不会有其他人从该通道接收更多)。
- 1 回答
- 0 关注
- 82 浏览
添加回答
举报
0/150
提交
取消