面试题答案
一键面试- 错误类型设计:
- 使用
std::error::Error
trait 来定义自定义错误类型。首先,创建一个枚举类型来包含所有可能的错误情况。例如:
use std::error::Error; use std::fmt; #[derive(Debug)] enum MyAppError { DatabaseError(String), NetworkError(String), // 其他自定义错误情况 } impl fmt::Display for MyAppError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { MyAppError::DatabaseError(s) => write!(f, "Database error: {}", s), MyAppError::NetworkError(s) => write!(f, "Network error: {}", s), } } } impl Error for MyAppError {}
- 使用
- 在异步函数间传递错误:
- 当定义异步函数时,在函数签名中使用
?
操作符来传递错误。例如:
use tokio::task; async fn async_function_1() -> Result<(), MyAppError> { // 可能会发生错误的异步操作 let result = task::spawn_blocking(|| { // 模拟数据库操作 Err(MyAppError::DatabaseError("Database connection failed".to_string())) }).await??; Ok(()) } async fn async_function_2() -> Result<(), MyAppError> { // 调用另一个异步函数并传递错误 async_function_1().await?; Ok(()) }
- 当定义异步函数时,在函数签名中使用
- 最终错误处理:
- 在顶层的异步函数中,使用
match
语句或者unwrap_or_else
等方法来处理错误。例如:
#[tokio::main] async fn main() { match async_function_2().await { Ok(()) => println!("All operations completed successfully"), Err(e) => eprintln!("An error occurred: {}", e), } }
- 在顶层的异步函数中,使用
async
/await
语法与错误处理的协同工作:async
函数返回一个Future
,而await
用于暂停当前异步函数的执行,等待Future
完成。当await
一个返回Result
类型的Future
时,如果Future
返回Err
,则await
表达式也会返回Err
,此时可以使用?
操作符将错误传递到上层调用者。- 例如在
async_function_2
中await
async_function_1
,如果async_function_1
返回错误,await
表达式会将这个错误返回,?
操作符会把错误传递给async_function_2
的调用者。这种机制使得错误能够在异步工作流中自然地向上传递,同时保持异步代码的简洁和可读性。