Skip to content

错误处理

  1. 首先 Rust 没有异常处理这个概念
  2. Rust 将错误分为两大类: 可恢复的错误(recoverable)和不可恢复的错误(unrecoverable)

处理不可恢复的错误

处理不可恢复的错误, 使用 panic! 宏

rust
fn main(){
    panic!("程序出错了");
}
rust
fn main(){
    // 访问一个数组不存在的索引
    // 这就是一个不可恢复的错误
    let arr = [1,2,3];
    println!("{}", arr[5]);
    // error: this operation will panic at runtime
    // index out of bounds: the length is 3 but the ind
}

处理可恢复的错误

处理可恢复的错误, 使用 Result 枚举

使用 Result 枚举

rust
use std::io;

// 尝试将字符串解析为 0 到 9 之间的数字
fn parse_to_number(str: &str) -> Result<usize, &str> {
    for i in 0..10 {
        let num_str = i.to_string();
        if num_str == str.trim() {
            return Ok(i);
        }
    }
    Err("Please enter a number between 0 and 9")
}

fn main() {
    println!("请输入一个0-9的数字:");
    let mut input = String::new();
    io::stdin().read_line(&mut input).expect("读取失败");

    // 移除换行符
    input.pop();

    let parse_result = parse_to_number(&input);

    match parse_result {
        Ok(n) => println!("你输入的是: {}", n),
        Err(e) => println!("错误: {}", e),
    };
}

使用 unwrap 和 expect 简化操作

rust
use std::io;

// 尝试将字符串解析为 0 到 9 之间的数字
fn parse_to_number(str: &str) -> Result<usize, &str> {
    for i in 0..10 {
        let num_str = i.to_string();
        if num_str == str.trim() {
            return Ok(i);
        }
    }
    Err("Please enter a number between 0 and 9")
}

fn main() {
    println!("请输入一个0-9的数字:");
    let mut input = String::new();
    io::stdin().read_line(&mut input).expect("读取失败");

    // 移除换行符
    input.pop();

    let res = parse_to_number(&input);

    res.expect("转换为数字失败"); // 匹配err的情况, 自动 panic!
    let num = res.unwrap();       // 匹配ok的情况, 直接获取到 Ok(x) 中的x值
    println!("num = {}", num);

    // 上面的代码就等同于这个 match 代码块
    // match res {
    //     Ok(num) => {
    //         println!("您输入的数字是: {}", num);
    //     },
    //     Err(e) => {
    //         panic!("转换数字失败:{}", e)
    //     },
    // }
}

传播错误

传播错误有快捷操作符: ?

Result 向上传播错误

rust
fn div(a:i32, b:i32) -> Result<i32, String> {
    if b == 0 {
        Err(String::from("division by zero"))
    } else {
        Ok(a / b)
    }
}

fn div_and_double(a:i32, b:i32) ->Result<i32, String> {
    // div(a, b) 函数有可能结果是 Err
    // 不立即处理错误, 而是向上传递错误
    // 让调用 div_and_double 的程序来处理
    // 这个就叫向上传递错误
    let x = match div(a, b) {
        Ok(v) => v,
        Err(e) => return Err(e),
    };

    Ok(x * 2)
}

fn main() {
    let x = div_and_double(6, 3).unwrap();
    println!("x={}", x);

    // Err
    div_and_double(6, 0).expect("error:failed to calculate 6 / 0 * 2");
}
rust
fn div_and_double(a:i32, b:i32) ->Result<i32, String> {
    let x = div(a, b)?;
    // 这个表达式就等同于:
    //let x = match div(a, b) {
    //    Ok(v) => v,
    //    Err(e) => return Err(e),
    //};

    Ok(x * 2)
}

Option 也可向上传播错误

rust
fn div(a:i32, b:i32) -> Option<i32> {
    if b == 0 {
        None
    } else {
        Some(a / b)
    }
}

fn div_and_double(a:i32, b:i32) -> Option<i32> {
    // match div(a, b) {
    //     Some(result) => Some(result * 2),
    //     None => None
    // }
    // 上面的match表达式就等同于:
    let x = div(a, b)?;
    Some(x * 2)
}

fn main() {
    let x = div_and_double(6, 3).unwrap();
    println!("x={}", x);

    div_and_double(6, 0).expect("error:failed to calculate 6 / 0 * 2");
}

Released under the MIT License.