跳到主要内容

异常处理

panic!

panic!表示程序无法从中恢复的状态。它会展开堆栈、清理资源,然后退出。这通常用于程序错误或理论上不可能达到的状态。


fn main() {
panic!("This is a panic message!"); // 主动抛出错误
}

当程序意外退出时,触发隐式 panic!,例如:

fn main() {
let v = vec![1, 2, 3];
println!("{}", v[99]); // 访问越界会触发 panic!
}

Option<T>

fn main() {
let v = vec![1, 2, 3];

// Attempt to get the element at index 1 (which is 2)
let second_element: Option<i32> = v.get(1);
match second_element {
Some(val) => println!("The second element is: {:?}", val), // Output: The second element is: 2
None => println!("There is no second element."),
}

// Attempt to get the element at index 99 (out of bounds)
let non_existent_element: Option<i32> = v.get(99);
match non_existent_element {
Some(val) => println!("The 99th element is: {:?}", val),
None => println!("Element at index 99 is: None"), // Output: Element at index 99 is: None
}
}

Result<T, E>

fn main() {
let x = 1;
let y = 0;

let q: Result<i32, String> = if y != 0 {
Ok(x / y)
} else {
Err("Division by zero encountered".to_string()) // Return a String error
};

match q {
Ok(val) => println!("{} / {} = {:?}", x, y, val),
Err(err_msg) => println!("Error during division: {}", err_msg),
// Output: Error during division: Division by zero encountered
}
}

unwrap() 和 expect() 让程序崩溃

unwrap() 让程序崩溃

unwrap()是 Option<T>Result<T, E> 类型的一个方法,用于提取其中的值。 对于 Option<T>,unwrap()会返回Some(T)中的值,如果是None,则会引发panic!。 对于 Result<T, E>,unwrap()会返回Ok(T)中的值,如果是Err(E),则会引发panic!。

fn main() {
let v = vec![1, 2, 3];
let second_element = v.get(1).unwrap(); // This will succeed and return 2
println!("The second element is: {}", second_element); // Output: The second element is: 2

expect() 让程序崩溃并提供错误信息

expect()与unwrap()类似,但它允许您提供一个自定义的错误消息,当发生错误时,这个消息会被打印出来,帮助您更好地理解发生了什么问题。

fn main() {
let v = vec![1, 2, 3];
let second_element = v.get(1).expect("Failed to get the second element!"); // This will succeed and return 2
println!("The second element is: {}", second_element); // Output: The second element is: 2
let non_existent_element = v.get(99).expect("Failed to get the 99th element!"); // This will panic with the provided message
}

当尝试访问索引99时,程序会崩溃,并输出以下错误

总结

摘要:unwrap()对比expect() 两者unwrap()都expect()用于从中获取内部值,Option或者Result当您确信该值应该存在时使用。

Option如果是None或,Result他们都会惊慌失措Err。

unwrap()出现故障,并显示通用的默认消息。

expect()None它会抛出一个自定义消息,该消息由您作为参数提供,这对于精确定位意外错误或异常的来源和上下文非常有价值Err。

?运算符

?运算符是Rust中用于简化错误处理的一种语法糖。它可以用于 Result<T, E> 类型的表达式,当表达式返回Err(E)时,?运算符会立即返回该错误,而不是继续执行后续代码。这使得代码更简洁和易读。

// question.rs
#![allow(unused)] // To suppress warnings for unused code during demonstration

// Question operator - ?

fn f1() -> Result<u32, String> {
println!("f1"); // Indicates function f1 was called
Ok(1) // Successfully returns 1
}

fn f2() -> Result<u32, String> {
println!("f2"); // Indicates function f2 was called
Ok(2) // Successfully returns 2
}

// 在用?运算符之前,需要 使用match来处理每个函数的结果
fn f1_f2_match() -> Result<u32, String> {
let res_1 = f1(); // Call f1, get Result<u32, String>
let out_1 = match res_1 {
Ok(num) => num, // If Ok, extract the number
Err(_) => { // If Err
return Err("error from f1".to_string()); // Return the error immediately
}
};

let res_2 = f2(); // Call f2, get Result<u32, String>
let out_2 = match res_2 {
Ok(num) => num, // If Ok, extract the number
Err(_) => { // If Err
return Err("error from f2".to_string()); // Return the error immediately
}
};

Ok(out_1 + out_2) // If both successful, sum and return Ok(sum)
}


// 使用?运算符简化错误处理
// 正确的就继续,错误的就直接返回错误
fn f1_f2_question() -> Result<u32, String> {
let out_1 = f1()?; // Call f1. If Ok, unwrap. If Err, return Err from f1_f2_question.
let out_2 = f2()?; // Call f2. If Ok, unwrap. If Err, return Err from f1_f2_question.
Ok(out_1 + out_2) // If both successful, sum and return Ok(sum)
}

📢 Share this article