Select 在被阻止的呼叫和频道上
Select on blocked call and channel
我很确定我以前看到过关于这个的问题,但现在找不到了。
本质上,我想 select
在被阻止的呼叫和频道上。
我知道我可以将阻塞的调用推送到 goroutine 中并通过通道等待结果,但感觉这是错误的解决方案。
有没有我想念的惯用方式来写这个?
最理想的情况是:
select {
case a <- c:
...
case ans := connection.Read():
...
}
如果你有一个通道和一个你想要的函数 select
,使用 goroutine 和一个通道是惯用的解决方案。请注意,如果从通道接收到一个值,那不会影响该功能,它会继续 运行。您可以使用 context.Context
来表示不再需要它的结果,它可能会提前终止。
如果允许重构,则可以“使”函数在同一通道上发送,因此您只需要从单个通道接收。
另一个重构想法是让函数监视同一个通道并尽早 return,因此您可以只进行一次调用而无需 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 上试用。
我很确定我以前看到过关于这个的问题,但现在找不到了。
本质上,我想 select
在被阻止的呼叫和频道上。
我知道我可以将阻塞的调用推送到 goroutine 中并通过通道等待结果,但感觉这是错误的解决方案。
有没有我想念的惯用方式来写这个?
最理想的情况是:
select {
case a <- c:
...
case ans := connection.Read():
...
}
如果你有一个通道和一个你想要的函数 select
,使用 goroutine 和一个通道是惯用的解决方案。请注意,如果从通道接收到一个值,那不会影响该功能,它会继续 运行。您可以使用 context.Context
来表示不再需要它的结果,它可能会提前终止。
如果允许重构,则可以“使”函数在同一通道上发送,因此您只需要从单个通道接收。
另一个重构想法是让函数监视同一个通道并尽早 return,因此您可以只进行一次调用而无需 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 上试用。