猿问

Golang 中的取消模式

这是来自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)。因此,我们可以从最快的工作人员(&ldquo;First Wins Pattern&rdquo;)收到结果,然后取消所有其他工人的工作并节省资源。


另一方面,根据规范:


对于语句中的所有情况,接收操作的通道操作数以及发送语句的通道和右侧表达式在输入&ldquo;select&rdquo;语句时按源顺序恰好计算一次。


据我了解,这意味着我们不能interrupt the workers,因为在任何情况下,所有工作人员都会评估功能replicas[i]query,然后才选择case <- done并完成他们的执行。


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


潇潇雨雨
浏览 83回答 1
1回答

慕桂英3389331

您的推理是正确的,网站上的措辞并不完全清楚。这个“构造”实现的是 goroutines 不会永远挂起,但是一旦搜索完成,goroutines 就会正确结束。那里什么也没有发生。通常,您不能从外部中断任何 goroutine,goroutine 本身必须支持某种终止(例如关闭通道context.Context等)。所以是的,在您发布的示例中,将同时启动所有搜索,最快的搜索结果将在到达时返回,只要搜索完成,其余的 goroutine 将继续运行。剩下的怎么办?其余的将被丢弃(case <- done将被选中,因为无缓冲的通道不能容纳任何元素,并且不会有其他人从该通道接收更多)。
随时随地看视频慕课网APP

相关分类

Go
我要回答