Rust错误处理终极指南:从panic!到Result的优雅之道嗨,各位Rustacean!你是否曾被程序的突然崩溃(panic)搞得一头雾水?或者面对复杂的match嵌套感到力不从心?Rust以其无与伦比的可靠性著称,而这背后最大的功臣就是其独特的错误处理机制。它在编译时就强
嗨,各位 Rustacean!你是否曾被程序的突然崩溃(panic)搞得一头雾水?或者面对复杂的 match 嵌套感到力不从心?
Rust 以其无与伦比的可靠性著称,而这背后最大的功臣就是其独特的错误处理机制。它在编译时就强制我们思考并处理潜在的失败,从根源上消除了大量的运行时错误。
本文将带你深入探索 Rust 的两大错误处理核心:用于不可恢复错误的 panic! 宏,以及用于可恢复错误的 Result 枚举。我们将从基本概念讲起,一路剖析 unwrap、expect、错误传播的 ? 运算符,并最终探讨何时应该让程序崩溃,何时应该优雅地返回一个结果。
读完本文,你将对 Rust 的错误处理哲学有更深刻的理解,写出更健壮、更优雅、更符合 Rust 风格的代码!
例子:Cargo.toml 文件
[package]
name = "vector_demo"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[profile.release]
panic = 'abort'
例子:src/main.rs 文件
fn main() {
// panic!("crash and burn");
let v = vec![1, 2, 3];
v[99]; // panic
}
enum Result<T, E> {
Ok(T),
Err(E),
}
use std::fs::File
fn main() {
let f = File::open("hello.txt");
}
use std::fs::File
fn main() {
let f = File::open("hello.txt");
let f = match f {
Ok(file) => file,
Err(error) => {
panic!("Error opening file {:?}", error)
}
};
}
use std::fs::File
fn main() {
let f = File::open("hello.txt");
let f = match f {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(e) => panic!("Error creating file: {:?}", e),
},
other_error = panic!("Error opening the file: {:?}", other_error),
},
};
}
use std::fs::File
fn main() {
let f = File::open("hello.txt").unwrap_or_else(|error| {
if error.kind() == ErrorKind::NotFound {
File::create("hello.txt").unwrap_or_else(|error| {
panic!("Error creating file: {:?}", error);
})
} else {
panic!("Error opening the file: {:?}", error);
}
});
}
use std::fs::File
fn main() {
let f = File::open("hello.txt");
let f = match f {
Ok(file) => file,
Err(error) => {
panic!("Error opening file {:?}", error)
}
};
let f = File::open("hello.txt").unwrap(); // 错误信息不可自定义
}
use std::fs::File
fn main() {
let f = File::open("hello.txt").expect("无法打开文件 hello.txt");
}
use std::fs::File;
use std::io;
use std::io::Read;
fn read_username_from_file() -> Result<String, io::Error> {
let f = File::open("hello.txt");
let mut f = match f {
Ok(file) => file,
Err(e) => return Err(e),
};
let mut s = String::new();
match f.read_to_string(&mut s) {
Ok(_) => Ok(s),
Err(e) => Err(e),
}
}
fn main() {
let result = read_username_from_file();
}
use std::fs::File;
use std::io;
use std::io::Read;
fn read_username_from_file() -> Result<String, io::Error> {
let mut f = File::open("hello.txt")?;
let mut s = String::new();
f.read_to_string(&mut s)?;
Ok(s)
}
fn main() {
let result = read_username_from_file();
}
Trait std::convert::From 上的 from 函数:
被 ? 所应用的错误,会隐式的被 from 函数处理
当 ? 调用 from 函数时:
用于:针对不同错误原因,返回同一种错误类型
链式调用
use std::fs::File;
use std::io;
use std::io::Read;
fn read_username_from_file() -> Result<String, io::Error> {
let mut s = String::new();
File::open("hello.txt")?.read_to_string(&mut s)?;
Ok(s)
}
fn main() {
let result = read_username_from_file();
}
use std::fs::File;
fn main() {
let f = File::open("hello.txt")?; // 报错
}
use std::error::Error;
use std::fs::File;
fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("hello.txt")?;
Ok(())
}
Box<dyn Error>
是 Trait 对象:
use std::net::IpAddr;
fn main() {
let home: IpAddr = "127.0.0.1".parse().unwrap();
}
fn main() {
loop {
// ...
let guess = "32";
let guess: i32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
if guess < 1 || guess > 100 {
println!("The secret number will be between 1 and 100.");
continue;
}
// ...
}
}
pub struct Guess {
value: i32,
}
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 || value >100 {
panic!("Guess value must be between 1 and 100, got {}", value);
}
Guess {value}
}
pub fn value(&self) -> i32 {
self.value
}
}
fn main() {
loop {
// ...
let guess = "32";
let guess: i32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
let guess = Guess::new(guess);
// ...
}
}
经过本文的探讨,我们可以对 Rust 的错误处理形成一个清晰的脉络:
总而言之,精通 Rust 的错误处理机制,是从“会写”到“写好” Rust 的必经之路。它不仅仅是一种语法,更是一种构建可靠软件的设计哲学。希望你从现在开始,能更加自信和优雅地处理代码中的每一个潜在错误。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!