Rust学习_3.错误处理
Rust 错误处理
一、错误的分类
- 可恢复(例如文件未找到);
- Result<T,E>
- 不可恢复(bug,例如访问索引超限);
- panic!
二、不可恢复的错误与panic!
1. 当 panic!宏执行:
- 你的程序会打印一个错误信息;
- 展开(unwind)、清理调用栈(Stack);
- 退出程序
2. 为应对panic,展开或中止调用栈
- 默认情况下,当panic发生:
- 程序展开调用栈(工作量大)
- Rust沿着调用栈往回走;
- 清理每个遇到的函数中的数据;
- 或终止调用栈
- 不进行清理,直接停止程序;
- 内存需要OS进行清理
- 程序展开调用栈(工作量大)
- 想让二进制文件更小,把设置从“展开”改为“中止“:
- 在
Cargo.toml
中适当的profile
部分设置:- panic=’abort’
- 在
三、Result 枚举与可恢复错误
1. Result 枚举
1 | enum Result<T,E>{ |
- T:操作成功情况下,Ok变体里返回的数据的类型;
- E:操作失败情况下,Err变体里返回的错误的类型;
2. 处理Result
的一种方式,match
表达式
3. unwrap
- match 表达式的一个快捷方式
- 如果Result结果是Ok,返回Ok里面的值;
- 如果Result结果是Err,调用panic!宏;
- 缺点:错误信息不能自定义!
1 | use std::fs::File; |
4. expect 可以自定义的unwrap
四、传播错误
1. 将错误返回给调用者
1 | fn read_username_from_file()->Result<String,io::Error>{ |
2. ?
运算符
?
运算符:传播错误的一种快捷方式;
- 如果Result 是 Ok: Ok中的值就是表达式的结果,然后继续执行程序;
- 如果Result 是Err:Err就是整个函数的返回值,就像使用了return;
1 | // 该函式等同于上面的函数 |
3. ?
与from
函数
Trait std::convert::From 上的
from
函数;- 用于错误之间的转换
被
?
所应用的错误,会隐式的被from
函数处理;当
?
调用from
函数时:- 它所接收的错误类型会转化为当前函数返回类型所定义的错误类型;
用于: 针对不同错误原因,返回同一种错误类型
- 只要每个错误类型实现了转换为所返回的错误类型的
from
函数;
- 只要每个错误类型实现了转换为所返回的错误类型的
链式调用:
1
2
3
4
5fn read_username_from_file()->Result<String,io::Error>{
let mut s = String::new();
File::open("hello.txt")?.read_to_string(&mut s)?;
Ok(s)
}?
运算符只能用于返回值为Result类型的函数
4. ?
运算符与main
函数
main 函数返回类型是();
main函数的返回类型也可以是:Result<T,E>;
1
2
3
4
5use std::error::Error;
fn main()->Result<(),Box<dyn Error>>{
let f = File::open("hello.txt")?;
Ok(())
}
五、 什么时候使用panic!
1. 总体原则
- 在定义一个可能失败的函数时,优先考虑返回Result;
- 否则就panic!
2. 编写示例、原型代码、测试
- 可以使用panic!
- 演示某些概念:unwrap;
- 原型代码:unwrap、expect;
- 测试:unwrap、expect;