Golang 中的取消模式
Posted
技术标签:
【中文标题】Golang 中的取消模式【英文标题】:Cancellation pattern in Golang 【发布时间】:2019-06-02 00:35:59 【问题描述】:这是来自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
提前中断worker而不等待完全执行(在我们的例子中执行replicas[i](query)
。因此,我们可以从最快的worker接收结果(“First Wins Pattern”),然后取消所有其他工作人员的工作并节省资源。
另一方面,根据specification:
对于语句中的所有情况,receive 的通道操作数 操作以及 send 的通道和右侧表达式 语句在输入时按源顺序只计算一次 “选择”语句。
据我了解,这意味着我们不能interrupt the workers
,因为无论如何,所有工作人员都会评估函数replicas[i]query
,然后才会选择case <- done
并完成它们的执行。
您能指出我推理中的错误吗?
【问题讨论】:
【参考方案1】:您的推理是正确的,网站上的措辞并不完全清楚。这个“构造”实现的是goroutines不会永远挂起,但是一旦搜索完成,goroutines就会正确结束。那里什么也没有发生。
一般来说,你不能从外部中断任何 goroutine,goroutine 本身必须支持某种终止(例如关闭通道,context.Context
等)。见cancel a blocking operation in Go。
所以是的,在您发布的示例中,所有搜索都将同时启动,最快的搜索结果将在到达时返回,其余的 goroutine 将继续运行,只要搜索完成。
其余的会发生什么?其余的将被丢弃(将选择case <- done
,因为无缓冲的通道不能容纳任何元素,并且不会有其他人从通道接收更多)。
您可以在此Go Playground example 中验证这一点。
【讨论】:
以上是关于Golang 中的取消模式的主要内容,如果未能解决你的问题,请参考以下文章
sql golang查询时,无效的内存地址或nil指针取消引用。