Result 的 Map 方法

RustRustBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在本实验中,我们将探索如何使用诸如 mapand_then 之类的组合器来处理 Rust 中 Result 类型的错误,从而更优雅地处理错误,如提供的示例所示。

注意:如果实验未指定文件名,你可以使用任何你想要的文件名。例如,你可以使用 main.rs,并通过 rustc main.rs &&./main 进行编译和运行。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/integer_types("Integer Types") rust/DataTypesGroup -.-> rust/string_type("String Type") rust/DataTypesGroup -.-> rust/type_casting("Type Conversion and Casting") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99240{{"Result 的 Map 方法"}} rust/integer_types -.-> lab-99240{{"Result 的 Map 方法"}} rust/string_type -.-> lab-99240{{"Result 的 Map 方法"}} rust/type_casting -.-> lab-99240{{"Result 的 Map 方法"}} rust/function_syntax -.-> lab-99240{{"Result 的 Map 方法"}} rust/expressions_statements -.-> lab-99240{{"Result 的 Map 方法"}} rust/operator_overloading -.-> lab-99240{{"Result 的 Map 方法"}} end

Resultmap 方法

在前一个示例的 multiply 函数中使用 unwrap 会导致程序恐慌,这可不是健壮的代码。通常,我们希望将错误返回给调用者,以便调用者决定处理错误的正确方式。

我们首先需要知道正在处理的是哪种错误类型。要确定 Err 类型,我们查看 parse() 函数,它是为 i32 类型实现的 FromStr 特征。因此,Err 类型被指定为 ParseIntError

在下面的示例中,直接使用 match 语句会使代码整体变得更加繁琐。

use std::num::ParseIntError;

// 重写返回类型后,我们使用模式匹配而不使用 `unwrap()`。
fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
    match first_number_str.parse::<i32>() {
        Ok(first_number)  => {
            match second_number_str.parse::<i32>() {
                Ok(second_number)  => {
                    Ok(first_number * second_number)
                },
                Err(e) => Err(e),
            }
        },
        Err(e) => Err(e),
    }
}

fn print(result: Result<i32, ParseIntError>) {
    match result {
        Ok(n)  => println!("n is {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

fn main() {
    // 这仍然会给出合理的答案。
    let twenty = multiply("10", "2");
    print(twenty);

    // 下面这个会给出更有用的错误信息。
    let tt = multiply("t", "2");
    print(tt);
}

幸运的是,Option 类型的 mapand_then 以及许多其他组合器也为 Result 类型实现了。Result 类型有完整的列表。

use std::num::ParseIntError;

// 与 `Option` 类型一样,我们可以使用 `map()` 等组合器。
// 这个函数与上面的函数功能相同,其含义是:
// 如果两个值都能从字符串解析成功,则相乘,否则传递错误。
fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
    first_number_str.parse::<i32>().and_then(|first_number| {
        second_number_str.parse::<i32>().map(|second_number| first_number * second_number)
    })
}

fn print(result: Result<i32, ParseIntError>) {
    match result {
        Ok(n)  => println!("n is {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

fn main() {
    // 这仍然会给出合理的答案。
    let twenty = multiply("10", "2");
    print(twenty);

    // 下面这个会给出更有用的错误信息。
    let tt = multiply("t", "2");
    print(tt);
}

总结

恭喜你!你已经完成了 ResultMap 实验。你可以在 LabEx 中练习更多实验来提升你的技能。