我很确定我之前已经看过一个问题,但是现在找不到。
本质上,我想select
通话和频道都被阻止。
我知道我可以将阻止的调用放入goroutine并通过通道等待结果,但是这感觉像是错误的解决方案。
是否有一种惯用的方式来写我所缺少的东西?
最理想的情况是:
select {
case a <- c:
...
case ans := connection.Read():
...
}
答案 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上尝试。