如何解决Rust编程中的错误问题

302 阅读3分钟

错误基本上是一种意外的行为,可能导致程序产生不期望的输出突然终止。错误处理是指处理失败的可能性的过程。在Rust中,错误可以被分为两大类:

  • 可恢复的
  • 不可恢复的

可恢复的错误

可恢复的错误是指那些不会导致程序突然终止的错误。比如找不到文件的错误。向用户报告这个问题并重试操作是合理的。你不要惊慌,而是发出一个OptionResult<T,E>。在这些情况下,你可以选择一个有效的值或一个无效的值

不可恢复的错误

不可恢复的错误是那些导致程序突然终止的错误。如果发生了不可恢复的错误,程序不能恢复到正常状态。在这种情况下,Rust有**panic!**宏。panic宏会导致程序突然退出。panic!会打印出失败信息。宏会将堆栈清理干净,然后退出。

处理错误的方法

在Rust中,有多种方法可以处理错误。有些是:

  • panic! marco
  • 结果<T,E>枚举
  • 选项枚举
  • 解包方法
  • 除去方法
  • ? 操作符

panic!Marco

panic!宏允许一个程序立即终止,并向程序的调用者提供反馈。我们只应该在我们的代码可能最终处于不良状态的条件下使用panic。

例子:

fn main() {
    panic!("panic condition !! ");
}

输出:

Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.99s
     Running `target/debug/playground`
thread 'main' panicked at 'panic condition !! ', src/main.rs:2:5

结果 <T,E> Enum

Rust不存在异常。它使用结果枚举,用来表示成功(Ok)或失败(Err)。

例子:

use std::fs::File;

fn main() {
    let file = File::open("test.txt");
   match file {
      Ok(file)=> println!("file found {:?}",file),
      Err(error)=> println!("file not found error {:?} ",error)
      }
}

输出

Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 2.48s
     Running `target/debug/playground`
file not found error Os { code: 2, kind: NotFound, message: "No such file or directory" }

选项 枚举

一个可选的值可以有一些 值或者没有值/

例子:

fn main() {
    let res = division(0,10);
    match res {
        Some(rem) => println!("Remainder is {}",rem),
        None => println!("Error : Divide by Zero")
    }
}

fn division(divisor:i32,dividend:i32) -> Option<i32> {
    if divisor == 0 {
        None
    } else {
        Some(dividend / divisor)
    }
}

输出

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.95s
     Running `target/debug/playground`
Error : Divide by Zero

Unwrap方法

Unwrap方法收到一个None时,会返回一个panic

例子:

fn main() {
    let res = division(0,10);
    println!("{}",res.unwrap());
}

fn division(divisor:i32,dividend:i32) -> Option<i32> {
    if divisor == 0 {
        None
    } else {
        Some(dividend / divisor)
    }
}

输出:

Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.96s
     Running `target/debug/playground`
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:3:23
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

除法

Except方法Unwrap方法相同,但它允许你设置一个错误信息。

例子 :

fn main() {
    let res = division(0,10);
    println!("{}",res.expect("Error : Divide by Zero"));
}

fn division(divisor:i32,dividend:i32) -> Option<i32> {
    if divisor == 0 {
        None
    } else {
        Some(dividend / divisor)
    }
}

输出:

Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.99s
     Running `target/debug/playground`
thread 'main' panicked at 'Error : Divide by Zero', src/main.rs:3:23
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

?操作符

我们可以通过使用匹配语句来解包Option 枚举,但通常使用**?**操作符更容易。

例子 :

#[derive(Debug)]
    enum MathError {
        DivisionByZero,
    }
fn main() {
    let res = check_division(0,10);
    println!("{:?}",res);
}

fn check_division(divisor: i32, dividend: i32) -> Result<i32,MathError>  {
        let rem = division(divisor, dividend)?;
        return Ok(rem)
    }

fn division(divisor:i32,dividend:i32) -> Result<i32,MathError> {
    if divisor == 0 {
        Err(MathError::DivisionByZero)
    } else {
        Ok(dividend/divisor)
    }
}

产出:

 Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.97s
     Running `target/debug/playground`
Err(DivisionByZero)

所以我希望你对Rust如何处理错误有了一些了解。谢谢你的阅读!!