本文属于我的 Rust 学习笔记 系列。
Rust 入门学习笔记以实际例子为主,讲解部分不是从零开始的,所以不建议纯萌新观看,读者最好拥有任意一种面向对象语言的基础,然后自己多多少少看过 Rust 的基本语法,刷过一点 rustlings。
来源:原子之音。当然也包含个人的一些补充。
视频
代码
Rust 进阶学习笔记以及实战的来源则五花八门,将会标注在下一行⬇️。
常见错误
错误
Rust 中的错误分为可恢复和不可恢复。
- 可恢复:有返回类型,可以为 Result 或 Option
- 不可恢复:panic! 终止当前线程
Result
Result 是一个枚举类型,通常用于表示函数执行的结果。
pub enum Result<T, E> {
Ok(T), Err(E), }
Option
Option 也是一个枚举类型,通常用于表示一个可能为空的值。
pub enum Option<T> {
None, Some(T), }
panic 宏
当程序遇到无法继续执行的错误时,可以使用panic!
宏来引发“恐慌”,导致程序立即终止并显示一条错误信息。
通常用于程序不能继续处理的情况下。
例子
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() {
match divide(1, 2) {
Ok(number) => println!("{}", number),
Err(err) => println!("{}", err),
}
match divide(1, 0) {
Ok(number) => println!("{}", number),
Err(err) => println!("{}", err),
}
let 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"),
}
let vec = vec![1, 2, 3, 4, 5]; vec[43];
}
错误结果处理
unwrap()
unwrap
并不是一个安全的方法。它是Result
和Option
类型提供的方法之一,可用于获取OK
或Some
的值,如果是Err
或None
会引发panic
。
一般只用于确定不会出现错误或错误不需要处理的情况。
?
运算符
?
用于简化Result
和Option
类型的错误传播,表示有预期之外的结果出现。它只能用于返回Result
或Option
的函数中,并且在函数内部也可以用于获取OK
或Some
的值,如果是Err
或None
则会立即提前返回。
例子
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>> {
let result_ok: Result<i32, &str> = Ok(32);
let value = result_ok.unwrap();
println!("{}", value); let result_ok: Result<i32, &str> = Ok(32);
let value = result_ok?;
println!("{}", value);
let numbers = vec![1, 3, 5];
match find_first_even(numbers) {
Some(number) => println!("first even {}", number),
None => println!("no such number"), }
match parse_numbers("d") {
Ok(i) => println!("parsed {}", i),
Err(err) => println!("failed to parse: {}", err), }
Ok(())
}
自定义错误类型
- 定义错误类型结构体。需要先创建一个结构体来表示错误类型,其中通常会包含一些字段来描述详细错误信息。
- 实现 Display 特质。
std::fmt::Display
特质可以定义如何展示错误信息,方便使错误能够以人类可读的方式打印出来。
- 实现 Error 特质。
std::error::Error
特质用于满足 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
}
}
fn func() -> Result<(), MyError> {
Err(MyError {
detail: "CustomError".to_owned(),
})
}
fn main() -> Result<(), MyError> {
match func() {
Ok(_) => println!("func ok"),
Err(err) => println!("Error: {}", err),
}
func()?;
println!("oo"); Ok(())
}