MST

星途 面试题库

面试题:Rust自定义错误类型与异步编程及错误处理链的结合

编写一个异步Rust程序,包含多个异步函数调用链。在其中一个异步函数中可能会出现自定义错误类型`AsyncError`。要求在整个异步调用链中正确传递和处理这个错误,并且当出现错误时,将错误信息以结构化的形式记录下来(可以使用`log` crate),同时确保程序在出现错误时能进行合适的清理操作。请实现`AsyncError`及其相关的错误处理逻辑。
27.3万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
use log::{error, info};
use std::error::Error;

// 自定义错误类型
#[derive(Debug)]
struct AsyncError {
    message: String,
}

impl std::fmt::Display for AsyncError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.message)
    }
}

impl Error for AsyncError {}

// 模拟异步函数1
async fn async_func1() -> Result<(), AsyncError> {
    info!("async_func1 is running");
    // 模拟可能出现的错误
    if rand::random::<bool>() {
        Err(AsyncError {
            message: "Error in async_func1".to_string(),
        })
    } else {
        Ok(())
    }
}

// 模拟异步函数2
async fn async_func2() -> Result<(), AsyncError> {
    info!("async_func2 is running");
    async_func1().await?;
    Ok(())
}

// 模拟异步函数3
async fn async_func3() -> Result<(), AsyncError> {
    info!("async_func3 is running");
    async_func2().await?;
    Ok(())
}

#[tokio::main]
async fn main() {
    env_logger::init();
    match async_func3().await {
        Ok(()) => info!("All async functions completed successfully"),
        Err(e) => {
            error!("An error occurred: {:?}", e);
            // 进行清理操作,这里简单打印一条清理信息
            info!("Performing cleanup operations");
        }
    }
}
  1. 自定义错误类型AsyncError
    • 实现了DebugDisplayError trait,以便于打印和处理错误。
  2. 异步函数调用链
    • async_func1:模拟一个可能出现错误的异步函数。
    • async_func2:调用async_func1,并传递其可能出现的错误。
    • async_func3:调用async_func2,并传递其可能出现的错误。
  3. 错误处理与记录
    • main函数中,使用match语句处理async_func3的结果。
    • 如果出现错误,使用log crate的error!宏记录错误信息,并打印清理操作的信息。
  4. 初始化日志
    • 使用env_logger::init()初始化日志系统,以便在程序运行时输出日志信息。

注意,上述代码中使用了rand crate来模拟随机出现的错误,需要在Cargo.toml中添加依赖:

[dependencies]
rand = "0.8.5"
log = "0.4.17"
env_logger = "0.9.0"
tokio = { version = "1.16.0", features = ["full"] }