我有一段代码需要从多个TcpStream中读取。其中一个TcpStream将始终存在,但另一个可能存在也可能不存在。
我之前写过这段代码,并且(天真地)在tokio select宏上使用了条件。不幸的是,我很快就发现该宏将首先评估arm(以获取future),然后才会检查条件,并根据此条件启动或跳过future。
结果,当我运行此代码时,我将得到以下错误信息:
我遇到的问题是如何处理这个问题? 我看到了以下几个解决方法, 但都不尽人意: - 添加if语句。如果stream2.is_some(),则使用带有两个分支的select,否则使用只有一个标记的select。这种方法可以解决问题,但会导致代码重复,使代码难以看懂。 - 我尝试了FutureUnordered方案。然而,考虑到上面的代码将在循环中执行,所以我放弃了这种方式,因为它不喜欢我在循环中尝试借用可变的事物。 - 我考虑过使用“假”的TcpStream来消除Option<>部分。但是,这看起来也很丑陋。 我正在寻找一种方法,使我能够保留对Option的select!操作。
我之前写过这段代码,并且(天真地)在tokio select宏上使用了条件。不幸的是,我很快就发现该宏将首先评估arm(以获取future),然后才会检查条件,并根据此条件启动或跳过future。
结果,当我运行此代码时,我将得到以下错误信息:
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:16:35
use tokio::io::AsyncReadExt;
use tokio::net::TcpStream;
#[tokio::main]
async fn main() {
let mut stream1 : TcpStream = TcpStream::connect("info.cern.ch:80").await.unwrap();
let mut stream2 : Option<TcpStream> = None;
let mut buf = vec![0_u8; 1024];
let mut buf2 = vec![0_u8; 1024];
tokio::select! {
result = stream1.read(&mut buf) => {
// do something here
}
result = stream2.as_mut().unwrap().read(&mut buf2), if stream2.is_some() => {
// do somethihng here
}
}
}
我遇到的问题是如何处理这个问题? 我看到了以下几个解决方法, 但都不尽人意: - 添加if语句。如果stream2.is_some(),则使用带有两个分支的select,否则使用只有一个标记的select。这种方法可以解决问题,但会导致代码重复,使代码难以看懂。 - 我尝试了FutureUnordered方案。然而,考虑到上面的代码将在循环中执行,所以我放弃了这种方式,因为它不喜欢我在循环中尝试借用可变的事物。 - 我考虑过使用“假”的TcpStream来消除Option<>部分。但是,这看起来也很丑陋。 我正在寻找一种方法,使我能够保留对Option的select!操作。
if
前提条件。该前提条件在<async expression>
之前进行评估。如果前提条件返回false
,则整个分支将被禁用。”但是当前版本如下:“此外,每个分支可能包括一个可选的if
前提条件。如果前提条件返回false
,则该分支将被禁用。提供的<async expression>
仍然会被评估,但是生成的 future 永远不会被轮询。” - cdhowie