Rust – 错误处理
错误基本上是一种意外的行为或事件,它可能导致程序产生不需要的输出或突然终止。错误是在他们的程序中没有人想要的东西。我们可以尝试查找和分析程序中可能导致错误的部分。一旦我们找到了这些部分,我们就可以定义这些部分在遇到错误时应该如何表现。这种为特定代码块查找和定义案例的过程就是我们所说的错误处理。我们应该记住的一件事是,我们无法完全消除错误,但我们可以尝试将它们最小化,或者至少减少它们对我们程序的影响。
在 Rust 中,错误可以分为两类,即可恢复的和不可恢复的
- 可恢复的错误: 可恢复错误是那些不会导致程序突然终止的错误。示例 - 当我们尝试获取不存在的文件或我们没有打开它的权限时。
- 不可恢复的错误:不可恢复的错误是那些导致程序突然终止的错误。示例 - 尝试访问大于数组大小的数组索引。
大多数语言不区分这两个错误并使用 Exception 类来克服它们,而 Rust 使用数据类型Result
我们将首先看看我们应该如何以及在哪里使用恐慌!宏。在它之前,我们将看到它对程序做了什么。
Rust
fn main() {
panic!("program crashed");
}
Rust
fn main() {
let v = vec![1, 2, 3];
println!("{}",v[3])
}
Rust
use std::fs::File;
fn main() {
let f = File::open("gfg.txt");
println!("{:?}",f);
}
Rust
use std::fs::File;
fn main() {
// file doesn't exist
let f = File::open("gfg.txt");/
match f {
Ok(file)=> {
println!("file found {:?}",file);
},
Err(_error)=> {
// replace it with whatever you want
// to do if file is not found
println!("file not found \n");
}
}
}
Rust
fn main(){
let result = eligible(13);
match result {
Ok(age)=>{
println!("Person eligible to vote with age={}",age);
},
Err(msg)=>{
println!("{}",msg);
}
}
}
fn eligible(age:i32)->Result {
if age>=18 {
return Ok(age);
} else {
return Err("Not Eligible..Wait for some years".to_string());
}
}
Rust
use std::fs::File;
fn main() {
let f = File::open("gfg.txt").unwrap();
}
Rust
use std::fs::File;
fn main() {
let f = File::open("hello.txt").expect("Failed to open gfg.txt");
}
输出:
thread 'main' panicked at 'program crashed', main.rs:2:7
因此,它基本上会停止程序的执行并打印我们在其参数中传递的内容。
恐慌!宏可能在我们使用的库文件中,让我们看看:
锈
fn main() {
let v = vec![1, 2, 3];
println!("{}",v[3])
}
输出:
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 3', main.rs:3:19
由于我们试图访问超出向量边界的元素,因此它称为恐慌!宏。
如果我们的代码可能最终处于错误状态,我们应该只在条件下使用恐慌。糟糕的状态是当某些假设、保证、合同或不变量被破坏时,例如当无效值、矛盾值或缺失值被传递给我们的代码以及以下至少一项时:-
- 如果在蓝色月亮中出现一次不良状态。
- 在此之后您的代码需要依赖于不处于这种糟糕状态。
- 在您使用的类型中编码此信息不是一个好方法。
可恢复的错误
Result
enum Result {
Ok(T),
Err(E),
}
T 和 E 是泛型类型参数,其中 T 表示将在 Ok 变体中的成功案例中返回的值的类型,而 E 表示将在 Err 变体中的失败案例中返回的错误类型。
锈
use std::fs::File;
fn main() {
let f = File::open("gfg.txt");
println!("{:?}",f);
}
输出:
Err(Os { code: 2, kind: NotFound, message: "No such file or directory" })
由于文件 gfg.txt 不存在,所以文件返回了 Err 实例。如果找到了文件 gfg.txt,则将返回该文件的一个实例。
如果像上述情况一样没有找到文件,那么最好让用户检查文件名、文件位置或再次提供文件规格或任何情况需要。
锈
use std::fs::File;
fn main() {
// file doesn't exist
let f = File::open("gfg.txt");/
match f {
Ok(file)=> {
println!("file found {:?}",file);
},
Err(_error)=> {
// replace it with whatever you want
// to do if file is not found
println!("file not found \n");
}
}
}
输出:
file not found
在上面的程序中,它基本上匹配了结果的返回类型,并相应地执行了任务。
让我们根据业务逻辑创建我们自己的错误。假设我们想要在 18 岁以下的人尝试申请选民 ID 时产生错误。
锈
fn main(){
let result = eligible(13);
match result {
Ok(age)=>{
println!("Person eligible to vote with age={}",age);
},
Err(msg)=>{
println!("{}",msg);
}
}
}
fn eligible(age:i32)->Result {
if age>=18 {
return Ok(age);
} else {
return Err("Not Eligible..Wait for some years".to_string());
}
}
输出:
Not Eligible..Wait for some years
如果我们想在遇到可恢复的错误后中止程序,那么我们可以使用 panic!宏并为了简化过程 Rust 提供了两个方法 unwrap() 和 expect()。
- 解包()
锈
use std::fs::File;
fn main() {
let f = File::open("gfg.txt").unwrap();
}
输出:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value:
Os { code: 2, kind: NotFound, message: "No such file or directory" }', main.rs:17:14
unwrap() 调用恐慌!宏在文件未找到的情况下,如果找到文件,则返回文件处理程序实例。虽然 unwrap() 使程序更短,但是当我们的程序中有太多 unwrap() 方法时,那么对于调用 panic 的 unwrap() 方法变得有点混乱!宏。所以我们需要一些可以产生定制消息的东西。在这种情况下,expect() 方法就派上用场了。
- 预计()
锈
use std::fs::File;
fn main() {
let f = File::open("hello.txt").expect("Failed to open gfg.txt");
}
输出:
thread 'main' panicked at 'Failed to open gfg.txt:
Os { code: 2, kind: NotFound, message: "No such file or directory" }', main.rs:17:14
我们传递了我们的信息来恐慌!宏通过预期的参数。