有没有办法像Go一样使用Rust的通道?我找不到任何相关资料。
对于那些不熟悉Go中select语句的人(来自文档):
"select"语句选择一组可能的发送或接收操作中的一个进行。它看起来类似于"switch"语句,但所有情况都涉及通信操作。具有RecvStmt的情况可以将RecvExpr的结果分配给一个或两个变量,可以使用短变量声明声明这些变量。RecvExpr必须是一个(可能带括号的)接收操作。最多只能有一个默认情况,并且可以出现在案例列表的任何位置。执行"select"语句需要几个步骤:
1. 对于语句中的所有情况,在进入"select"语句时,接收操作的通道操作数以及发送语句的通道和右侧表达式将按源顺序评估一次。结果是一组要从中接收或发送的通道以及相应的值。该评估中的任何副作用都将发生,无论选择哪个(如果有)通信操作进行。具有短变量声明或赋值的RecvStmt左侧的表达式尚未评估。
2. 如果其中一个或多个通信可以进行,则通过统一的伪随机选择选择可以进行的单个通信。否则,如果存在默认情况,则选择该情况。如果没有默认情况,则"select"语句将阻塞,直到至少有一个通信可以进行。
3. 除非所选情况是默认情况,否则将执行相应的通信操作。
4. 如果所选情况是具有短变量声明或赋值的RecvStmt,则将评估左侧表达式并分配接收到的值(或值)。
5. 执行所选情况的语句列表。
由于在nil通道上的通信永远无法进行,因此仅具有nil通道且没有默认情况的select会永久阻塞。
例如,如何在Rust中编写此代码?
func search(ctx context.Context, result chan IResult, q string) error {
// googleSearch and bingSearch will return IResult interface channel
google := googleSearch(q)
bing := bingSearch(q)
t := time.After(time.Second)
for {
select {
// at any point if caller cancel the operation we return
case <- ctx.Done():
return nil
case r, ok := <- google:
if !ok { // check if channel is closed
google = nil
if bing == nil { // we are done
return nil
}
continue
}
// sending the google search result to result channel. ( channel to channel )
result <- r
case r, ok := <- bing:
if !ok {
bing = nil
if google == nil {
return nil
}
continue
}
result <- r
case <- t:
// this function never lives for more then 1 second
return fmt.Errorf("timeout")
}
}
return nil
}
recv_timeout
怎么样?如果可以在库中实现,我们就不需要特殊的语法或宏。 - mcartonselect
能否在Rust中轻松实现。 - Shepmastercrossbeam_channel
似乎也有类似于 Go 的 channel 和 select。但是我对 Go 的了解基本上止步于 "lol no generics"。 - mcarton