Golang中的取消模式

时间:2019-01-07 10:44:59

标签: go select channel worker cancellation

这里是50 Shades Of Go: Traps, Gotchas and Common mistakes的引文:

  

您还可以使用特殊的取消渠道来中断   工人。

const url1 = '/user/{username}/edit'
const url2 = '/user/harry/edit'

const split1 = url1.split('/')
const split2 = url2.split('/')

let matchCount = 0
let notMatchedCount = 0

split1.map(x => {
    if(x === split2[x]) {
        matchCount++
    } else {
        notMatchedCount++
    }
})

if(matchCount > notMatchedCount) {
    console.log('Match Found')
} else {
    console.log('Match not found')
}

据了解,这意味着我们使用通道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。因此,我们可以收到结果从最快的工作程序(“第一个获胜模式”)中删除,然后取消所有其他工作程序中的工作并节省资源。

另一方面,根据specification

  

对于语句中的所有情况,receive的通道操作数   操作以及send的通道和右侧表达式   输入后,按源顺序对语句进行一次精确评估   “选择”语句。

据我了解,这意味着我们不能replicas[i](query),因为在任何情况下,所有工作人员都将评估函数interrupt the workers,然后才选择replicas[i]query并完成执行。

您能指出我推理中的错误吗?

1 个答案:

答案 0 :(得分:3)

您的推论是正确的,网站上的措词并不完全清楚。该“构造”实现的结果是,goroutine不会永远挂着,但是一旦搜索完成,goroutine就会正确结束。那里什么也没发生。

通常,您无法从外部中断任何goroutine,goroutine本身必须支持某种终止(例如,关闭通道,context.Context等)。参见cancel a blocking operation in Go

因此,是的,在您发布的示例中,所有搜索将同时启动,最快的搜索结果将在到达时返回,其余goroutines将在搜索结束后继续运行。 / p>

其余的怎么办?其余的将被丢弃(将选择{case <- done,因为未缓冲的通道无法容纳任何元素,并且不会再有其他人从该通道接收更多元素)。

您可以在此Go Playground example中对此进行验证。