《深入Rust系统编程》2.6 错误处理

2.6 错误处理 错误处理是编程中不可避免的一部分,Rust 提供了强大的错误处理机制,使开发者能够编写健壮、可靠的代码。Rust 的错误处理机制基于 Result 和 Option 枚举,并结合 match 表达式、? 运算符和 panic! 宏来实现。

2.6 错误处理

错误处理是编程中不可避免的一部分,Rust 提供了强大的错误处理机制,使开发者能够编写健壮、可靠的代码。Rust 的错误处理机制基于 ResultOption 枚举,并结合 match 表达式、? 运算符和 panic! 宏来实现。

2.6.1 Result 枚举

Result 枚举用于表示可能成功或失败的操作,其定义如下:

enum Result<T, E> {
    Ok(T),
    Err(E),
}
  • T 是操作成功时返回的值的类型。
  • E 是操作失败时返回的错误的类型。

1. 处理 Result:

可以使用 match 表达式来处理 Result 枚举:

fn divide(numerator: i32, denominator: i32) -> Result<i32, String> {
    if denominator == 0 {
        Err(String::from("division by zero"))
    } else {
        Ok(numerator / denominator)
    }
}

fn main() {
    let result = divide(10, 2);

    match result {
        Ok(value) => println!("Result: {}", value),
        Err(error) => println!("Error: {}", error),
    }
}

2. ? 运算符:

? 运算符用于简化 Result 枚举的处理,如果 ResultOk,则返回 Ok 中的值,如果是 Err,则提前返回错误:

fn divide(numerator: i32, denominator: i32) -> Result<i32, String> {
    if denominator == 0 {
        Err(String::from("division by zero"))
    } else {
        Ok(numerator / denominator)
    }
}

fn calculate() -> Result<i32, String> {
    let result1 = divide(10, 2)?;
    let result2 = divide(result1, 0)?;
    Ok(result2)
}

fn main() {
    match calculate() {
        Ok(value) => println!("Result: {}", value),
        Err(error) => println!("Error: {}", error),
    }
}

2.6.2 Option 枚举

Option 枚举用于表示可能为空的值,其定义如下:

enum Option<T> {
    Some(T),
    None,
}
  • T 是值存在时的类型。

1. 处理 Option:

可以使用 match 表达式来处理 Option 枚举:

fn find(haystack: &str, needle: char) -> Option<usize> {
    for (index, char) in haystack.chars().enumerate() {
        if char == needle {
            return Some(index);
        }
    }
    None
}

fn main() {
    let haystack = "hello";
    let needle = 'l';

    match find(haystack, needle) {
        Some(index) => println!("Found at index: {}", index),
        None => println!("Not found"),
    }
}

2. unwrapexpect 方法:

unwrapexpect 方法用于从 Option 中提取值,如果 OptionNone,则会引发 panic:

fn main() {
    let some_value = Some(5);
    let none_value: Option<i32> = None;

    println!("{}", some_value.unwrap()); // 输出 5
    println!("{}", none_value.unwrap()); // panic!
    println!("{}", none_value.expect("Expected a value")); // panic with custom message
}

2.6.3 panic!

panic! 宏用于在程序遇到不可恢复的错误时终止程序执行:

fn main() {
    panic!("crash and burn");
}

2.6.4 自定义错误类型

可以定义自定义错误类型来表示特定的错误情况:

#[derive(Debug)]
enum MyError {
    DivisionByZero,
    NegativeNumber,
}

fn divide(numerator: i32, denominator: i32) -> Result<i32, MyError> {
    if denominator == 0 {
        Err(MyError::DivisionByZero)
    } else if numerator < 0 || denominator < 0 {
        Err(MyError::NegativeNumber)
    } else {
        Ok(numerator / denominator)
    }
}

fn main() {
    let result = divide(10, -2);

    match result {
        Ok(value) => println!("Result: {}", value),
        Err(error) => println!("Error: {:?}", error),
    }
}

2.6.5 错误传播

可以使用 ? 运算符将错误传播到调用函数:

fn calculate() -> Result<i32, MyError> {
    let result1 = divide(10, 2)?;
    let result2 = divide(result1, -2)?;
    Ok(result2)
}

fn main() {
    match calculate() {
        Ok(value) => println!("Result: {}", value),
        Err(error) => println!("Error: {:?}", error),
    }
}

2.6.6 代码实例

1. 处理 Result:

fn divide(numerator: i32, denominator: i32) -> Result<i32, String> {
    if denominator == 0 {
        Err(String::from("division by zero"))
    } else {
        Ok(numerator / denominator)
    }
}

fn main() {
    let result = divide(10, 2);

    match result {
        Ok(value) => println!("Result: {}", value),
        Err(error) => println!("Error: {}", error),
    }
}

2. 使用 ? 运算符:

fn divide(numerator: i32, denominator: i32) -> Result<i32, String> {
    if denominator == 0 {
        Err(String::from("division by zero"))
    } else {
        Ok(numerator / denominator)
    }
}

fn calculate() -> Result<i32, String> {
    let result1 = divide(10, 2)?;
    let result2 = divide(result1, 0)?;
    Ok(result2)
}

fn main() {
    match calculate() {
        Ok(value) => println!("Result: {}", value),
        Err(error) => println!("Error: {}", error),
    }
}

3. 处理 Option:

fn find(haystack: &str, needle: char) -> Option<usize> {
    for (index, char) in haystack.chars().enumerate() {
        if char == needle {
            return Some(index);
        }
    }
    None
}

fn main() {
    let haystack = "hello";
    let needle = 'l';

    match find(haystack, needle) {
        Some(index) => println!("Found at index: {}", index),
        None => println!("Not found"),
    }
}

4. 自定义错误类型:

#[derive(Debug)]
enum MyError {
    DivisionByZero,
    NegativeNumber,
}

fn divide(numerator: i32, denominator: i32) -> Result<i32, MyError> {
    if denominator == 0 {
        Err(MyError::DivisionByZero)
    } else if numerator < 0 || denominator < 0 {
        Err(MyError::NegativeNumber)
    } else {
        Ok(numerator / denominator)
    }
}

fn main() {
    let result = divide(10, -2);

    match result {
        Ok(value) => println!("Result: {}", value),
        Err(error) => println!("Error: {:?}", error),
    }
}

5. 错误传播:

fn calculate() -> Result<i32, MyError> {
    let result1 = divide(10, 2)?;
    let result2 = divide(result1, -2)?;
    Ok(result2)
}

fn main() {
    match calculate() {
        Ok(value) => println!("Result: {}", value),
        Err(error) => println!("Error: {:?}", error),
    }
}

2.6.7 总结

Rust 提供了强大的错误处理机制,使开发者能够编写健壮、可靠的代码。ResultOption 枚举用于表示可能失败或为空的操作,match 表达式、? 运算符和 panic! 宏用于处理错误。掌握 Rust 的错误处理机制,可以编写出更安全、更可靠的 Rust 代码。

以下是一些学习 Rust 错误处理的资源:

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页