开篇:错误处理的生存哲学
在Rust的平行宇宙里,错误分为两种人格:
- panic! → 核按钮💣(不可恢复,全系统警报)
- Result → 灭火器🧯(可控制,局部处理)
rust
// 核按钮使用示范(请勿轻易尝试)
fn launch_nukes() {
panic!("💥 核弹发射密码错误!");
}
// 灭火器使用示范
fn fight_fire() -> Result<(), String> {
Ok(()) // 一切正常时返回氧气面罩
}
第一章:世界末日按钮(panic!)
1.1 核爆基础操作
场景类比:当图书馆发现致命病毒书
rust
fn check_book_safety(page: usize) {
let library = ["📖", "📚", "🦠"];
if page >= library.len() {
panic!("⚠️ 发现第{}页的病毒书,紧急闭馆!", page);
}
println!("安全阅读第{}页", page);
}
// check_book_safety(3); // 触发世界末日
执行结果:
text
thread 'main' panicked at '⚠️ 发现第3页的病毒书,紧急闭馆!'
生存法则:
- 像处理生化危机一样果断
- 打印错误信息并立即终止程序
- 适合不可修复的严重错误
1. 2 自动引爆机制
场景类比:数组越界如同踩到地雷
rust
fn step_on_landmine() {
let minefield = [1, 2, 3];
println!("正在探测第4个位置...");
let _bomb = minefield[3]; // 自动触发panic
}
爆炸现场:
text
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 3'
生存技巧:
- 编译器是排雷专家
- 开发时开启调试模式(RUST_BACKTRACE=1)
- 生产环境避免踩雷
第二章:灭火的艺术(Result)
2.1 消防工具包(Result枚举)
工具组成:
- Ok(T) → 完好的消防栓💦
- Err(E) → 漏水的软管🚱
rust
fn check_fire_extinguisher(pressure: u32) -> Result<String, String> {
if pressure > 50 {
Ok("压力正常,可以灭火".to_string())
} else {
Err("⚠️ 压力不足,需要更换罐体!".to_string())
}
}
let status = check_fire_extinguisher(30);
println!("灭火器状态:{:?}", status);
// 输出:Err("⚠️ 压力不足,需要更换罐体!")
消防守则:
- 必须处理两种可能情况
- 使用match进行模式匹配
- 适用于预期内的错误
2.2 错误传递接力
场景类比:消防队接警流程
rust
fn fire_alarm_system() -> Result<(), String> {
let step1 = check_fire_extinguisher(60)?;
let step2 = check_sprinkler_system()?;
Ok(())
}
fn check_sprinkler_system() -> Result<(), String> {
// 模拟检查失败
Err("🚒 喷淋系统故障,水管漏水!".to_string())
}
报警记录:
text
Err("🚒 喷淋系统故障,水管漏水!")
接力规则:
?
运算符是快速传递错误的绿色通道- 遇到Err立即返回
- 函数返回类型必须兼容
第三章:危险走钢丝(unwrap与expect)
3.1 无保护走钢丝(unwrap)
场景类比:不使用安全网的高空作业
rust
let safety_net = "安全网已安装".to_string();
let net_status = Some(safety_net);
println!("工人状态:{}", net_status.unwrap()); // 安全作业
// let fall = None.unwrap(); // 空中坠落触发panic
安全提示:
- 仅在确定有值时使用
- 相当于 "我确信这里不会出错"
- 生产代码慎用
3.2 带提示的冒险(expect)
场景类比:挂着警告牌的钢丝
rust
let balance_pole = Some("平衡杆");
println!("表演者:{}", balance_pole.expect("⚠️ 平衡杆失踪!"));
// let disaster = None.expect("救命啊!"); // 带信息的坠落
坠落报告:
text
thread 'main' panicked at '救命啊!'
安全升级:
- 比unwrap更有信息量
- 依然属于危险操作
- 适合快速原型开发
终章:综合灾难演练------太空站紧急处理系统
rust
use std::fs::File;
use std::io::Read;
fn main() -> Result<(), String> {
// 第一阶段:氧气系统检测
let o2_status = check_oxygen_system(80)?;
println!("{}", o2_status);
// 第二阶段:读取舱压数据
let pressure = read_pressure_data("pressure.txt")?;
println!("当前舱压:{}千帕", pressure);
// 第三阶段:终极安全检查
verify_emergency_exits(); // 可能触发panic
Ok(())
}
fn check_oxygen_system(level: u32) -> Result<String, String> {
match level {
0..=20 => Err("☠️ 氧气严重不足!".into()),
21..=50 => Ok("⚠️ 氧气量偏低,建议补充".into()),
_ => Ok("✅ 氧气系统正常".into())
}
}
fn read_pressure_data(path: &str) -> Result<f32, String> {
let mut file = File::open(path)
.map_err(|e| format!("🛸 无法读取压力文件:{}", e))?;
let mut content = String::new();
file.read_to_string(&mut content)
.map_err(|e| format!("📉 数据解析失败:{}", e))?;
content.trim().parse()
.map_err(|_| "🔢 舱压数据格式异常".into())
}
fn verify_emergency_exits() {
let exits_functional = false;
assert!(exits_functional, "🚨 紧急出口验证失败!");
}
演练结果分析
情景一:正常流程
text
✅ 氧气系统正常
当前舱压:101.3千帕
thread 'main' panicked at '🚨 紧急出口验证失败!'
情景二:氧气不足
text
Err("☠️ 氧气严重不足!")
情景三:压力文件丢失
text
✅ 氧气系统正常
Err("🛸 无法读取压力文件:No such file or directory")
生存手册精华版
- panic! 是最后的逃生舱------只在真正危机时使用
- Result 是太空站的冗余系统------优雅处理预期问题
- ? 运算符像紧急通道------快速传递问题
- unwrap 像不系安全带的太空行走------刺激但危险
- assert! 是自动化安检仪------及早发现问题
记住:在Rust的太空站里,错误处理不是可选配件