MST

星途 面试题库

面试题:Rust Result类型与错误链在异步编程及泛型中的深度应用

在一个异步的网络请求场景中,使用`async`/`await`语法进行多个请求,并对每个请求结果进行处理。请求可能出现网络错误(`std::io::Error`),解析响应可能出现格式错误(自定义`ResponseParseError`)。要求使用Result类型处理这些错误,同时在泛型函数中实现该逻辑,以便不同类型的请求都能复用该逻辑,并合理构建错误链,使错误在异步调用栈中准确传递,最后展示如何在顶层异步函数中进行统一的错误处理。
50.5万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
use std::io;
use thiserror::Error;

// 自定义解析错误
#[derive(Error, Debug)]
pub enum ResponseParseError {
    #[error("Invalid response format")]
    InvalidFormat,
}

// 模拟网络请求函数
async fn mock_network_request<T>(url: &str) -> Result<T, io::Error> where T: std::str::FromStr {
    // 实际实现中这里会进行网络请求并返回结果
    Ok("".parse().map_err(|_| io::Error::new(io::ErrorKind::Other, "parse error"))?)
}

// 解析响应函数
fn parse_response<T>(response: &str) -> Result<T, ResponseParseError> where T: std::str::FromStr {
    response.parse().map_err(|_| ResponseParseError::InvalidFormat)
}

// 泛型函数处理多个请求
async fn process_requests<T>(urls: &[&str]) -> Result<Vec<T>, RequestError> where T: std::str::FromStr {
    let mut results = Vec::new();
    for url in urls {
        let response = mock_network_request::<T>(url).await?;
        let parsed = parse_response(&response.to_string())?;
        results.push(parsed);
    }
    Ok(results)
}

// 统一错误类型
#[derive(Error, Debug)]
pub enum RequestError {
    #[error("Network error: {0}")]
    Network(#[from] io::Error),
    #[error("Parse error: {0}")]
    Parse(#[from] ResponseParseError),
}

// 顶层异步函数及错误处理
#[tokio::main]
async fn main() {
    let urls = &["url1", "url2"];
    match process_requests::<i32>(urls).await {
        Ok(results) => println!("Results: {:?}", results),
        Err(e) => eprintln!("Error: {:?}", e),
    }
}
  1. 自定义解析错误:定义了ResponseParseError枚举类型来表示解析响应时的格式错误。
  2. 模拟网络请求函数mock_network_request函数模拟实际的网络请求,它是异步的,并返回Result<T, io::Error>,其中T是可以从字符串解析的类型。
  3. 解析响应函数parse_response函数将字符串解析为指定类型T,如果解析失败返回ResponseParseError
  4. 泛型函数处理多个请求process_requests函数是泛型函数,接受一个URL数组,对每个URL发起网络请求,解析响应,并将结果收集到一个Vec中。它使用Result处理网络错误和解析错误,并通过?操作符合理构建错误链。
  5. 统一错误类型RequestError枚举类型将网络错误和解析错误统一起来,方便在顶层进行处理。
  6. 顶层异步函数及错误处理:在main函数中,调用process_requests并通过match语句处理可能出现的错误。