错误处理
- 首先 Rust 没有异常处理这个概念
- Rust 将错误分为两大类: 可恢复的错误(recoverable)和不可恢复的错误(unrecoverable)
处理不可恢复的错误
处理不可恢复的错误, 使用 panic! 宏
rust
fn main(){
panic!("程序出错了");
}
rust
fn main(){
// 访问一个数组不存在的索引
// 这就是一个不可恢复的错误
let arr = [1,2,3];
println!("{}", arr[5]);
// error: this operation will panic at runtime
// index out of bounds: the length is 3 but the ind
}
处理可恢复的错误
处理可恢复的错误, 使用 Result 枚举
使用 Result 枚举
rust
use std::io;
// 尝试将字符串解析为 0 到 9 之间的数字
fn parse_to_number(str: &str) -> Result<usize, &str> {
for i in 0..10 {
let num_str = i.to_string();
if num_str == str.trim() {
return Ok(i);
}
}
Err("Please enter a number between 0 and 9")
}
fn main() {
println!("请输入一个0-9的数字:");
let mut input = String::new();
io::stdin().read_line(&mut input).expect("读取失败");
// 移除换行符
input.pop();
let parse_result = parse_to_number(&input);
match parse_result {
Ok(n) => println!("你输入的是: {}", n),
Err(e) => println!("错误: {}", e),
};
}
使用 unwrap 和 expect 简化操作
rust
use std::io;
// 尝试将字符串解析为 0 到 9 之间的数字
fn parse_to_number(str: &str) -> Result<usize, &str> {
for i in 0..10 {
let num_str = i.to_string();
if num_str == str.trim() {
return Ok(i);
}
}
Err("Please enter a number between 0 and 9")
}
fn main() {
println!("请输入一个0-9的数字:");
let mut input = String::new();
io::stdin().read_line(&mut input).expect("读取失败");
// 移除换行符
input.pop();
let res = parse_to_number(&input);
res.expect("转换为数字失败"); // 匹配err的情况, 自动 panic!
let num = res.unwrap(); // 匹配ok的情况, 直接获取到 Ok(x) 中的x值
println!("num = {}", num);
// 上面的代码就等同于这个 match 代码块
// match res {
// Ok(num) => {
// println!("您输入的数字是: {}", num);
// },
// Err(e) => {
// panic!("转换数字失败:{}", e)
// },
// }
}
传播错误
传播错误有快捷操作符: ?
Result 向上传播错误
rust
fn div(a:i32, b:i32) -> Result<i32, String> {
if b == 0 {
Err(String::from("division by zero"))
} else {
Ok(a / b)
}
}
fn div_and_double(a:i32, b:i32) ->Result<i32, String> {
// div(a, b) 函数有可能结果是 Err
// 不立即处理错误, 而是向上传递错误
// 让调用 div_and_double 的程序来处理
// 这个就叫向上传递错误
let x = match div(a, b) {
Ok(v) => v,
Err(e) => return Err(e),
};
Ok(x * 2)
}
fn main() {
let x = div_and_double(6, 3).unwrap();
println!("x={}", x);
// Err
div_and_double(6, 0).expect("error:failed to calculate 6 / 0 * 2");
}
rust
fn div_and_double(a:i32, b:i32) ->Result<i32, String> {
let x = div(a, b)?;
// 这个表达式就等同于:
//let x = match div(a, b) {
// Ok(v) => v,
// Err(e) => return Err(e),
//};
Ok(x * 2)
}
Option 也可向上传播错误
rust
fn div(a:i32, b:i32) -> Option<i32> {
if b == 0 {
None
} else {
Some(a / b)
}
}
fn div_and_double(a:i32, b:i32) -> Option<i32> {
// match div(a, b) {
// Some(result) => Some(result * 2),
// None => None
// }
// 上面的match表达式就等同于:
let x = div(a, b)?;
Some(x * 2)
}
fn main() {
let x = div_and_double(6, 3).unwrap();
println!("x={}", x);
div_and_double(6, 0).expect("error:failed to calculate 6 / 0 * 2");
}