选择阻止的呼叫和频道

时间:2020-09-04 11:05:13

标签: go concurrency channel

我很确定我之前已经看过一个问题,但是现在找不到。

本质上,我想select通话和频道都被阻止。

我知道我可以将阻止的调用放入goroutine并通过通道等待结果,但是这感觉像是错误的解决方案。

是否有一种惯用的方式来写我所缺少的东西?

最理想的情况是:

select {
case a <- c:
  ...
case ans := connection.Read():
  ...
}

1 个答案:

答案 0 :(得分:4)

如果您有一个频道和想要select的功能,则使用goroutine和一个频道是惯用的解决方案。但是请注意,如果从通道接收到一个值,则不会影响该功能,它将继续运行。您可以使用context.Context来表示不再需要其结果,并且可能会提前终止。

但是,如果允许重构,则可以“使”函数在同一通道上发送,因此您只需要从单个通道接收即可。

另一个重构思路是该函数监视相同的频道并提早返回,因此您可以只进行一次调用而无需使用select

请注意,如果您需要在许多地方执行此操作,则可以创建一个辅助函数来异步启动它:

func launch(f func()) <-chan struct{} {
    done := make(chan struct{})
    go func() {
        defer close(done)
        f()
    }()
    return done
}

示例功能:

func test() {
    time.Sleep(time.Second)
}

然后使用它:

select {
case a := <-c:
    fmt.Println("received from channel:", a)
case <-launch(test):
    fmt.Println("test() finished")

}

Go Playground上尝试。

相关问题