不灭的焱

革命尚未成功,同志仍须努力 下载Java21

作者:AlbertWen  添加时间:2026-07-15 12:00:01  修改时间:2026-07-22 12:06:58  分类:01.Rust编程  编辑

目录

在 Rust 中:

.await
.map_err(...)

通常表示:

  1. 使用 .await 等待异步操作完成;
  2. 异步操作返回一个 Result<T, E>
  3. 使用 .map_err() 把原来的错误 E 转换成另一种错误类型。

基本写法

let result = async_operation()
    .await
    .map_err(|err| {
        // 将原错误转换成新错误
        MyError::RequestFailed(err.to_string())
    })?;

等价于:

let result = async_operation().await;

let result = result.map_err(|err| {
    MyError::RequestFailed(err.to_string())
})?;

.await 返回什么

例如:

async fn query_user() -> Result<String, std::io::Error> {
    Ok("Albert".to_string())
}

调用:

let user = query_user().await;

此时 user 的类型不是 String,而是:

Result<String, std::io::Error>

所以可以继续调用:

let user = query_user()
    .await
    .map_err(|err| err.to_string())?;

这里把:

std::io::Error

转换成了:

String

map_err() 的作用

假设原始结果为:

Result<T, E>

调用:

result.map_err(|error| new_error)

会得到:

Result<T, NewError>

它只转换 Err,不会修改 Ok

例如:

let result: Result<i32, &str> = Err("数字解析失败");

let new_result: Result<i32, String> =
    result.map_err(|err| format!("业务错误:{}", err));

结果是:

Err("业务错误:数字解析失败")

如果原结果是:

Ok(100)

那么调用 map_err() 后仍然是:

Ok(100)

常见完整案例

自定义错误类型

use thiserror::Error;

#[derive(Debug, Error)]
enum AppError {
    #[error("读取文件失败:{0}")]
    FileRead(String),
}

async fn read_config() -> Result<String, std::io::Error> {
    tokio::fs::read_to_string("config.toml").await
}

async fn load_config() -> Result<String, AppError> {
    let content = read_config()
        .await
        .map_err(|err| AppError::FileRead(err.to_string()))?;

    Ok(content)
}

执行过程是:

read_config()

返回 Future,然后:

.await

等待 Future 完成,得到:

Result<String, std::io::Error>

再通过:

.map_err(|err| AppError::FileRead(err.to_string()))

转换为:

Result<String, AppError>

最后:

?

表示:

  • Ok(content):取出 content,继续执行;
  • Err(error):立即返回 AppError

.map_err() 里面必须传闭包

错误写法:

request()
    .await
    .map_err();

因为 map_err() 不知道要把错误转换成什么。

正确写法:

request()
    .await
    .map_err(|err| err.to_string())?;

或者:

request()
    .await
    .map_err(AppError::Request)?;

枚举构造函数可以直接传给 map_err

例如:

#[derive(Debug)]
enum AppError {
    Io(std::io::Error),
}

可以写成:

let content = tokio::fs::read_to_string("config.toml")
    .await
    .map_err(AppError::Io)?;

它等价于:

let content = tokio::fs::read_to_string("config.toml")
    .await
    .map_err(|err| AppError::Io(err))?;

map_err()map() 的区别

result.map(...)

转换成功值 Ok

let result: Result<i32, String> = Ok(10);

let result = result.map(|value| value * 2);

// Ok(20)

而:

result.map_err(...)

转换错误值 Err

let result: Result<i32, &str> = Err("失败");

let result = result.map_err(|err| err.to_string());

// Err(String)

最常见的组合

let value = some_async_function()
    .await
    .map_err(|err| AppError::Internal(err.to_string()))?;

可以理解为:

等待异步函数执行完成;如果失败,就把原始错误转换为 AppError::Internal,然后通过 ? 向上返回;如果成功,就取出成功值。