2.6 错误处理
错误处理是编程中不可避免的一部分,Rust 提供了强大的错误处理机制,使开发者能够编写健壮、可靠的代码。Rust 的错误处理机制基于 Result
和 Option
枚举,并结合 match
表达式、?
运算符和 panic!
宏来实现。
2.6.1 Result
枚举
Result
枚举用于表示可能成功或失败的操作,其定义如下:
1
2
3
4
|
enum Result<T, E> {
Ok(T),
Err(E),
}
|
T
是操作成功时返回的值的类型。
E
是操作失败时返回的错误的类型。
1. 处理 Result
:
可以使用 match
表达式来处理 Result
枚举:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
fn divide(numerator: i32, denominator: i32) -> Result<i32, String> {
if denominator == 0 {
Err(String::from("division by zero"))
} else {
Ok(numerator / denominator)
}
}
fn main() {
let result = divide(10, 2);
match result {
Ok(value) => println!("Result: {}", value),
Err(error) => println!("Error: {}", error),
}
}
|
2. ?
运算符:
?
运算符用于简化 Result
枚举的处理,如果 Result
是 Ok
,则返回 Ok
中的值,如果是 Err
,则提前返回错误:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
fn divide(numerator: i32, denominator: i32) -> Result<i32, String> {
if denominator == 0 {
Err(String::from("division by zero"))
} else {
Ok(numerator / denominator)
}
}
fn calculate() -> Result<i32, String> {
let result1 = divide(10, 2)?;
let result2 = divide(result1, 0)?;
Ok(result2)
}
fn main() {
match calculate() {
Ok(value) => println!("Result: {}", value),
Err(error) => println!("Error: {}", error),
}
}
|
2.6.2 Option
枚举
Option
枚举用于表示可能为空的值,其定义如下:
1
2
3
4
|
enum Option<T> {
Some(T),
None,
}
|
1. 处理 Option
:
可以使用 match
表达式来处理 Option
枚举:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
fn find(haystack: &str, needle: char) -> Option<usize> {
for (index, char) in haystack.chars().enumerate() {
if char == needle {
return Some(index);
}
}
None
}
fn main() {
let haystack = "hello";
let needle = 'l';
match find(haystack, needle) {
Some(index) => println!("Found at index: {}", index),
None => println!("Not found"),
}
}
|
2. unwrap
和 expect
方法:
unwrap
和 expect
方法用于从 Option
中提取值,如果 Option
是 None
,则会引发 panic:
1
2
3
4
5
6
7
8
|
fn main() {
let some_value = Some(5);
let none_value: Option<i32> = None;
println!("{}", some_value.unwrap()); // 输出 5
println!("{}", none_value.unwrap()); // panic!
println!("{}", none_value.expect("Expected a value")); // panic with custom message
}
|
2.6.3 panic!
宏
panic!
宏用于在程序遇到不可恢复的错误时终止程序执行:
1
2
3
|
fn main() {
panic!("crash and burn");
}
|
2.6.4 自定义错误类型
可以定义自定义错误类型来表示特定的错误情况:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#[derive(Debug)]
enum MyError {
DivisionByZero,
NegativeNumber,
}
fn divide(numerator: i32, denominator: i32) -> Result<i32, MyError> {
if denominator == 0 {
Err(MyError::DivisionByZero)
} else if numerator < 0 || denominator < 0 {
Err(MyError::NegativeNumber)
} else {
Ok(numerator / denominator)
}
}
fn main() {
let result = divide(10, -2);
match result {
Ok(value) => println!("Result: {}", value),
Err(error) => println!("Error: {:?}", error),
}
}
|
2.6.5 错误传播
可以使用 ?
运算符将错误传播到调用函数:
1
2
3
4
5
6
7
8
9
10
11
12
|
fn calculate() -> Result<i32, MyError> {
let result1 = divide(10, 2)?;
let result2 = divide(result1, -2)?;
Ok(result2)
}
fn main() {
match calculate() {
Ok(value) => println!("Result: {}", value),
Err(error) => println!("Error: {:?}", error),
}
}
|
2.6.6 代码实例
1. 处理 Result
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
fn divide(numerator: i32, denominator: i32) -> Result<i32, String> {
if denominator == 0 {
Err(String::from("division by zero"))
} else {
Ok(numerator / denominator)
}
}
fn main() {
let result = divide(10, 2);
match result {
Ok(value) => println!("Result: {}", value),
Err(error) => println!("Error: {}", error),
}
}
|
2. 使用 ?
运算符:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
fn divide(numerator: i32, denominator: i32) -> Result<i32, String> {
if denominator == 0 {
Err(String::from("division by zero"))
} else {
Ok(numerator / denominator)
}
}
fn calculate() -> Result<i32, String> {
let result1 = divide(10, 2)?;
let result2 = divide(result1, 0)?;
Ok(result2)
}
fn main() {
match calculate() {
Ok(value) => println!("Result: {}", value),
Err(error) => println!("Error: {}", error),
}
}
|
3. 处理 Option
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
fn find(haystack: &str, needle: char) -> Option<usize> {
for (index, char) in haystack.chars().enumerate() {
if char == needle {
return Some(index);
}
}
None
}
fn main() {
let haystack = "hello";
let needle = 'l';
match find(haystack, needle) {
Some(index) => println!("Found at index: {}", index),
None => println!("Not found"),
}
}
|
4. 自定义错误类型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#[derive(Debug)]
enum MyError {
DivisionByZero,
NegativeNumber,
}
fn divide(numerator: i32, denominator: i32) -> Result<i32, MyError> {
if denominator == 0 {
Err(MyError::DivisionByZero)
} else if numerator < 0 || denominator < 0 {
Err(MyError::NegativeNumber)
} else {
Ok(numerator / denominator)
}
}
fn main() {
let result = divide(10, -2);
match result {
Ok(value) => println!("Result: {}", value),
Err(error) => println!("Error: {:?}", error),
}
}
|
5. 错误传播:
1
2
3
4
5
6
7
8
9
10
11
12
|
fn calculate() -> Result<i32, MyError> {
let result1 = divide(10, 2)?;
let result2 = divide(result1, -2)?;
Ok(result2)
}
fn main() {
match calculate() {
Ok(value) => println!("Result: {}", value),
Err(error) => println!("Error: {:?}", error),
}
}
|
2.6.7 总结
Rust 提供了强大的错误处理机制,使开发者能够编写健壮、可靠的代码。Result
和 Option
枚举用于表示可能失败或为空的操作,match
表达式、?
运算符和 panic!
宏用于处理错误。掌握 Rust 的错误处理机制,可以编写出更安全、更可靠的 Rust 代码。
以下是一些学习 Rust 错误处理的资源: