Rust学习笔记 11:错误处理
对应代码文件:src/bin/11_error_handling.rs
运行命令:
1 | cargo run --bin lesson11_error_handling |
学习目标
Rust 把错误分成可恢复错误和不可恢复错误。可恢复错误通常用 Result 表达。
错误处理是 Rust 代码可读性的重要部分。你需要明确说明失败时程序应该如何反应。
- 理解
Result<T, E>的含义。 - 会用
match处理成功和失败。 - 掌握
unwrap、expect的风险和适用场景。 - 理解
?运算符如何传播错误。
核心概念速查
| 术语 | 基本意思 | 本节用途 |
|---|---|---|
| Result | 表示成功或失败的枚举。 | Ok(T) 是成功,Err(E) 是错误。 |
| panic | 不可恢复错误,程序通常终止当前线程。 | 适合违反程序假设的严重问题。 |
| unwrap | 取出 Ok 或 Some 的值,失败时 panic。 |
初学和测试可用,生产代码要谨慎。 |
| expect | 类似 unwrap,但可以提供 panic 信息。 | 比 unwrap 更容易定位原因。 |
| ? 运算符 | 成功时取值,失败时提前返回错误。 | 用于简化错误传播。 |
完整源码
1 | use std::fs; |
运行与观察
使用 cargo run --bin lesson11_error_handling 可以只运行本节示例。
这里的 --bin 后面写的是 Cargo.toml 中声明的目标名,不是 .rs 文件名。文件名用于组织源码,bin 名用于 Cargo 运行。
建议初学时先直接运行,再修改一两行代码观察编译器提示。Rust 的错误信息通常会指出所有权、类型或借用规则哪里不满足。
逐段解读
返回 Result
示例函数用 Result<i32, String> 表示可能成功也可能失败。
match 处理
match result 分别处理 Ok(value) 和 Err(message)。
expect
用于明确表达“这里失败就说明输入不符合预期”。
? 传播
在返回 Result 的函数中,? 可以减少嵌套匹配。
专有词语详解
Result
表示成功或失败的枚举。
Ok(T) 是成功,Err(E) 是错误。
panic
不可恢复错误,程序通常终止当前线程。
适合违反程序假设的严重问题。
unwrap
取出 Ok 或 Some 的值,失败时 panic。
初学和测试可用,生产代码要谨慎。
expect
类似 unwrap,但可以提供 panic 信息。
比 unwrap 更容易定位原因。
? 运算符
成功时取值,失败时提前返回错误。
用于简化错误传播。
初学者拓展
Rust 没有异常机制作为主路径。失败是类型的一部分,调用方必须面对。
Result<T, E> 中 T 是成功值类型,E 是错误值类型。
? 只能用于返回兼容错误类型的函数。它不是忽略错误,而是把错误交给上层。
库代码通常返回 Result,应用入口可以选择打印错误、重试或退出。
常见误区
- 不要在所有地方使用
unwrap()。它会让程序在错误输入时直接崩溃。 expect()的信息应该说明你假设了什么,而不是写空泛的error。- 使用
?前确认当前函数返回Result或兼容类型。 - 不要吞掉错误。至少应该记录、返回或明确处理。
进阶练习与参考答案
练习 1:安全除法
要求:写函数处理除以零错误。
参考答案:
1 | fn divide(a: i32, b: i32) -> Result<i32, String> { |
解释:除数为 0 是可预期错误,用 Result 返回给调用方。
练习 2:用 ? 传播错误
要求:解析两个字符串并相加。
参考答案:
1 | fn parse_sum(a: &str, b: &str) -> Result<i32, std::num::ParseIntError> { |
解释:? 在解析失败时直接返回 Err,成功时取出数字。
练习 3:替换 unwrap
要求:把 unwrap 改成 match 处理。
参考答案:
1 | fn main() { |
解释:match 让失败路径也被明确写出来。