错误处理哲学
JavaScript 的 try-catch 有个根本问题:你不知道一个函数会不会抛出异常,除非读文档或踩坑。
Rust 的规则:可能失败的操作,必须在类型签名里体现。
对比:错误处理
JS
TypeScript(try-catch)// 你不知道这个函数会不会 throw
async function readFile(path: string): Promise<string> {
try {
return await fs.readFile(path, 'utf8');
} catch (e) {
throw new Error(`读取失败:${e}`);
}
}Rs
Rust(Result)use std::fs;
// 签名直接告诉你:可能成功返回 String,也可能失败返回 io::Error
fn read_file(path: &str) -> Result<String, std::io::Error> {
fs::read_to_string(path) // ? 会传播错误
}
// 调用方必须处理两种情况
match read_file("data.txt") {
Ok(content) => println!("{}", content),
Err(e) => eprintln!("错误:{}", e),
}→
Result 让错误变成了类型的一部分。你不能忽略它,编译器会提醒你——这就是 Rust 错误处理的核心价值。
? 操作符:优雅的错误传播
? 类似 await——它简化了错误传播的样板代码:
use std::io;
use std::fs;
fn read_username() -> Result<String, io::Error> {
// ? 的意思:成功就继续,失败就立刻返回 Err
let content = fs::read_to_string("username.txt")?;
Ok(content.trim().to_string())
}
// 链式 ? 操作
fn parse_config() -> Result<Config, io::Error> {
let json = fs::read_to_string("config.json")?;
let config: Config = serde_json::from_str(&json)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
Ok(config)
}自定义错误:thiserror
[dependencies]
thiserror = "1"
anyhow = "1"use thiserror::Error;
#[derive(Error, Debug)]
enum AppError {
#[error("IO 错误:{0}")]
Io(#[from] std::io::Error),
#[error("解析错误(第 {line} 行):{msg}")]
Parse { line: usize, msg: String },
#[error("用户 {0} 不存在")]
NotFound(String),
}
// ? 自动把 io::Error 转为 AppError::Io
fn process_file(path: &str) -> Result<Vec<Record>, AppError> {
let content = std::fs::read_to_string(path)?; // io::Error → AppError::Io
parse_records(&content)
}库代码用 thiserror:定义精确的错误类型,让调用方可以 match 不同情况。
应用代码用 anyhow:快速传播错误,加上有用的上下文信息。
anyhow:应用级错误处理
use anyhow::{Context, Result};
fn load_app() -> Result<App> {
let config = fs::read_to_string("config.json")
.context("找不到配置文件 config.json")?;
let settings: Settings = serde_json::from_str(&config)
.context("配置文件格式错误")?;
App::init(settings).context("应用初始化失败")
}实战项目:CSV 解析器
实战项目
CSV 文件解析器
60 分钟中级
读取 CSV 文件,解析每行数据,处理格式错误、类型错误、文件不存在等所有可能的错误情况,输出清晰的错误报告。
thiserror 自定义错误? 错误传播anyhow::Context错误信息友好化
cargo new csv-parser && cd csv-parser实战视频
Rust 错误处理:Result 与 ?
0:00 / 0:00CC
Result 类型、? 操作符、thiserror 和 anyhow 的使用场景对比。