使用async
/await
语法实现异步函数
- 定义异步函数:在Rust中,使用
async
关键字定义一个异步函数。例如,假设要编写一个异步获取网络数据的函数:
use std::net::TcpStream;
use std::io::{Read, Write};
use futures::stream::StreamExt;
use tokio::net::TcpListener;
async fn fetch_data() -> Result<String, Box<dyn std::error::Error>> {
let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
let request = "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n";
stream.write_all(request.as_bytes()).await?;
let mut response = String::new();
stream.read_to_string(&mut response).await?;
Ok(response)
}
- 调用异步函数:在另一个异步函数或
main
函数(如果使用tokio
运行时)中调用这个异步函数。例如:
#[tokio::main]
async fn main() {
match fetch_data().await {
Ok(data) => println!("Data fetched: {}", data),
Err(e) => eprintln!("Error: {}", e),
}
}
处理错误以确保性能不受较大影响
- 使用
?
操作符:在异步函数内部,使用?
操作符来传播错误。这使得代码简洁,并且当错误发生时,函数会立即返回,避免不必要的计算。如上面fetch_data
函数中TcpStream::connect
、write_all
和read_to_string
操作都使用了?
操作符。
- 在调用处处理错误:在调用异步函数的地方,通过
match
语句或unwrap_or_else
等方法处理错误。如在main
函数中使用match
语句来决定如何处理成功和失败的情况。
- 避免不必要的错误处理开销:不要在异步函数内部进行过于复杂的错误处理逻辑,除非必要。简单的错误传播能保持代码的简洁性和高性能。如果需要对错误进行特定处理,可以在调用处集中处理,而不是在每个可能出错的异步操作内部。