错误基本上是一种意外的行为,可能导致程序产生不期望的输出或突然终止。错误处理是指处理失败的可能性的过程。在Rust中,错误可以被分为两大类:
- 可恢复的
- 不可恢复的
可恢复的错误
可恢复的错误是指那些不会导致程序突然终止的错误。比如找不到文件的错误。向用户报告这个问题并重试操作是合理的。你不要惊慌,而是发出一个Option或Result<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如何处理错误有了一些了解。谢谢你的阅读!!