MST
星途 面试题库

面试题:Rust函数定义与异步编程及错误处理

编写一个异步Rust函数,该函数接受一个URL字符串作为参数,尝试从该URL下载数据。在下载过程中,如果发生网络错误、解析错误(假设数据应解析为JSON格式)等情况,需要进行恰当的错误处理。函数应该返回下载并解析后的数据。请详细说明你如何定义该异步函数,如何处理不同类型的错误,以及如何确保资源的正确释放。同时,解释在异步环境下,Rust函数的执行流程与普通函数有哪些不同。
39.4万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
use reqwest::Error as ReqwestError;
use serde::de::DeserializeOwned;
use serde_json::Error as JsonError;

// 定义一个枚举来统一处理不同类型的错误
#[derive(Debug)]
enum DownloadError {
    Network(ReqwestError),
    Json(JsonError),
}

impl From<ReqwestError> for DownloadError {
    fn from(e: ReqwestError) -> Self {
        DownloadError::Network(e)
    }
}

impl From<JsonError> for DownloadError {
    fn from(e: JsonError) -> Self {
        DownloadError::Json(e)
    }
}

// 异步函数,接受URL字符串作为参数,返回解析后的数据
async fn download_and_parse<T: DeserializeOwned>(url: &str) -> Result<T, DownloadError> {
    let client = reqwest::Client::new();
    let response = client.get(url).send().await?;
    let data = response.json::<T>().await?;
    Ok(data)
}

错误处理

  1. 网络错误:使用reqwest库进行HTTP请求,send方法返回Result类型,当发生网络错误时会返回Err,我们通过?操作符将ReqwestError转换为DownloadError::Network
  2. 解析错误:使用response.json::<T>()解析JSON数据,当解析失败时会返回Err,我们通过?操作符将JsonError转换为DownloadError::Json

资源释放

  1. reqwest::Client是可复用的,在函数结束时会自动释放资源。
  2. response在解析完成后,其占用的资源也会被正确释放,因为json方法会消费response

异步函数执行流程与普通函数的不同

  1. 普通函数:按顺序依次执行,遇到函数调用会阻塞当前线程直到被调用函数返回。函数执行过程中不会被其他任务打断,除非发生中断或异常。
  2. 异步函数
    • 非阻塞执行:异步函数在执行到await关键字时,会暂停当前函数的执行,将控制权交回给调用者(通常是事件循环),允许其他异步任务继续执行。当await的任务完成时,异步函数会从暂停的地方继续执行。
    • 异步任务调度:异步函数内部的任务由异步运行时(如tokio)进行调度管理。运行时会在多个异步任务之间切换执行,以充分利用CPU资源,实现高效的并发执行。
    • 状态机生成:Rust编译器会将异步函数编译为状态机,状态机通过枚举来表示函数的不同执行状态,以此来管理函数的暂停和恢复执行。