文章目录
- 一、错误处理之:Result、Option以及panic!宏
- 1.Result
- 2.Option
- 3.panic!
- 二、错误处理之:unwrap()与'?'
- 1.unwrap()
- 2.?运算符
- 三、自定义一个Error类型
- 参考
一、错误处理之:Result、Option以及panic!宏
Rust中的错误可以分为两种
-
Recoverable error:有返回类型
(1)返回Result类型
(2)返回Option类型 -
Unrecoverable type:没有返回类型,直接崩溃
panicmacro将终止当前线程
1.Result
Result是一个枚举类型,有两个变体:0k和Err。它通常用于表示函数的执行结果,其中ok表示成功的结果,Err表示出现了错误
pub enum Result<T,E>{Ok(T),Err (E),
}
2.Option
·Option也是一个枚举类型,有两个变体:Some和None。它通常用于表示一个可能为空的值。
pub enum Option<T>{
None,
Some (T),
}
3.panic!
当程序遇到无法继续执行的错误时,可以使用panic!宏来引发恐慌。恐慌会导致程序立即终止,并显示一条错误消息。
Example:
fn divide(a: i32, b: i32) -> Result<f64, String> {if b == 0 {return Err(String::from("cannot be zero"));}let a = a as f64;let b = b as f64;Ok(a / b)
}fn find_element(array: &[i32], target: i32) -> Option<usize> {for (index, element) in array.iter().enumerate() {if (*element) == target {return Some(index);}}None
}fn main() {// 处理result结果只能使用matchmatch divide(1, 2) {Ok(number) => println!("{}", number),Err(err) => println!("{}", err),}match divide(1, 0) {Ok(number) => println!("{}", number),Err(err) => println!("{}", err),}// optionlet arr = [1, 2, 3, 4, 5];match find_element(&arr, 4) {Some(index) => println!("found in {}", index),None => println!("None"),}match find_element(&arr, 7) {Some(index) => println!("found in {}", index),None => println!("None"),}// paniclet vec = vec![1, 2, 3, 4, 5];vec[43]; //数组越界
}
编译及运行:
cargo runFinished `dev` profile [unoptimized + debuginfo] target(s) in 0.00sRunning `target/debug/ch17_error`
0.5
cannot be zero
found in 3
None
thread 'main' panicked at src/main.rs:43:8:
index out of bounds: the len is 5 but the index is 43
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
~/installer/rust/project/ch17_error master x101
RUST_BACKTRACE=1 cargo runFinished `dev` profile [unoptimized + debuginfo] target(s) in 0.00sRunning `target/debug/ch17_error`
0.5
cannot be zero
found in 3
None
thread 'main' panicked at src/main.rs:43:8:
index out of bounds: the len is 5 but the index is 43
stack backtrace:0: rust_begin_unwindat /rustc/1e4f10ba6476e48a42a79b9f846a2d9366525b9e/library/std/src/panicking.rs:665:51: core::panicking::panic_fmtat /rustc/1e4f10ba6476e48a42a79b9f846a2d9366525b9e/library/core/src/panicking.rs:75:142: core::panicking::panic_bounds_checkat /rustc/1e4f10ba6476e48a42a79b9f846a2d9366525b9e/library/core/src/panicking.rs:285:53: <usize as core::slice::index::SliceIndex<[T]>>::indexat /home/wangji/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:304:104: core::slice::index::<impl core::ops::index::Index<I> for [T]>::indexat /home/wangji/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:16:95: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::indexat /home/wangji/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3344:96: ch17_error::mainat ./src/main.rs:43:87: core::ops::function::FnOnce::call_onceat /home/wangji/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
二、错误处理之:unwrap()与’?’
1.unwrap()
注意:该方法并不安全
unwrap()是 Result 和 Option 类型提供的方法之一。它是一个简便的方法,用于获取 Ok 或 Some 的值,如果是 Err 或 None 则会引发 panic
2.?运算符
?用于简化 Result 或 Option 类型的错误传播。它只能用于返回 Result 或Option 的函数中,并且在函数内部可以像使用unwrap()一样访问 Ok 或 Some的值,但是如果是 Err 或 None 则会提前返回。
Example:
use std::num::ParseIntError;fn find_first_even(numbers: Vec<i32>) -> Option<i32> {let first_even = numbers.iter().find(|&num| num % 2 == 0)?;print!("Option");Some(*first_even)
}// 传递错误
fn parse_numbers(input: &str) -> Result<i32, ParseIntError> {let val = input.parse::<i32>()?;Ok(val)
}fn main() -> Result<(), Box<dyn std::error::Error>> {// Result<i32, &str>let result_ok: Result<i32, &str> = Ok(32);let value = result_ok.unwrap();println!("{}", value);// Result<i32, &str> 直接panic// let result_ok: Result<i32, &str> = Err("ff");// let value = result_ok.unwrap();// println!("{}", value);// 使用?let result_ok: Result<i32, &str> = Ok(100);let value = result_ok?;println!("{}", value);// 找到第一个偶数let numbers = vec![1, 3, 5];match find_first_even(numbers) {Some(_) => println!("first even 1"),None => println!("no such number"),}match parse_numbers("d") {Ok(i) => println!("parsed {}", i),Err(err) => println!("failed to parse: {}", err),}Ok(())
}
编译及运行:
cargo runCompiling ch18_question_unwrap v0.1.0 (/home/wangji/installer/rust/project/ch18_question_unwrap)Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23sRunning `target/debug/ch18_question_unwrap`
32
100
no such number
failed to parse: invalid digit found in string
三、自定义一个Error类型
1.定义错误类型结构体:创建一个结构体来表示你的错误类型,通常包含一些字段来描述错误的详细信息。
2.实现 std::fmt::Display trait:实现这个 trait以定义如何展示错误信息。这是为了使错误能够以人类可读的方式打印出来。
3.实现 std::error::Error trait:实现这个 trait以满足Rust的错误处理机制的要求。
#[derive(Debug)]
struct MyError {detail: String,
}impl std::fmt::Display for MyError {fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {write!(f, "Custom Error: {}", self.detail)}
}impl std::error::Error for MyError {fn description(&self) -> &str {&self.detail}// &String String&自动转=> &str 字符串字面量
}fn func() -> Result<(), MyError> {Err(MyError {detail: "CustomError".to_owned(),})// Ok(())
}// 等价于fn main()->Result<(), MyError>
// 所有实现std::error::Error 的东西,都可以使用Box<dyn std::error::Error>进行返回
fn main() -> Result<(), Box<dyn std::error::Error>> {match func() {Ok(_) => println!("func ok"),Err(err) => println!("Error: {}", err),}func()?;println!("oo"); //以前前面?的原因,且返回的是Err,这里则不会输出Ok(())
}
编译及运行
cargo runFinished `dev` profile [unoptimized + debuginfo] target(s) in 0.05sRunning `target/debug/ch19_custom_err`
Error: Custom Error: CustomError
Error: MyError { detail: "CustomError" }
参考
- 2024 Rust现代实用教程