use std::error::Error;
use serde::{Serialize, Deserialize};
use tracing::{error, info};
// 定义自定义错误类型
#[derive(Debug, Serialize, Deserialize)]
struct AppError {
message: String,
}
impl Error for AppError {}
impl std::fmt::Display for AppError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.message)
}
}
// 示例异步函数,会返回AppError
async fn inner_function() -> Result<(), AppError> {
// 模拟一些可能出错的操作
Err(AppError { message: "Inner function error".to_string() })
}
// 调用inner_function并传播错误
async fn middle_function() -> Result<(), AppError> {
inner_function().await?;
Ok(())
}
// 顶层函数,捕获错误并记录日志
async fn top_level_function() {
match middle_function().await {
Ok(_) => info!("All operations completed successfully"),
Err(e) => {
let json_error = serde_json::to_string(&e).unwrap_or_else(|_| "Serialization error".to_string());
error!("Error occurred: {}", json_error);
}
}
}
代码说明
- 定义自定义错误类型
AppError
:实现了 Error
特质以及 Display
特质,并且为了方便转为JSON格式,实现了 Serialize
和 Deserialize
特质。
inner_function
:模拟一个可能会返回 AppError
的异步函数。
middle_function
:调用 inner_function
并使用 ?
操作符来传播错误。
top_level_function
:调用 middle_function
并在 match
块中捕获错误。将错误转换为JSON格式并记录到日志中。
优化措施
- 在定义
AppError
时,避免使用动态分配(如 Box<dyn Error>
),这样可以减少不必要的装箱操作。
- 使用
?
操作符在异步函数链中简洁地传播错误,使得错误处理代码更加清晰,也有助于编译器进行优化。