Rust - panic!
不可恢复的错误与panic!
1、Rust的错误处理
- Rust的可靠性:错误处理
2、错误的分类
- 可恢复 : 如文件未找到
- 不可恢复 : bug, 如数组越界
3、Rust没有其他语言的异常的机制
- 对于可恢复的错误的方法: Result<T,E>
- 对不可恢复的错误的方法: panic!宏
1、不可恢复错误
1、当panic!宏执行
- 程序会打印一个错误信息
- 展开 、 清理调用栈
- 退出程序
2、为了应对展开和清理调用栈
- 默认情况下当panic发生
- Rust沿着调用栈往会走
- 清理每个遇到函数中的数据
- 或者可以立即中止调用栈
- 不进行清理,直接停止程序
- 后续需要OS去清理内存
3、想让二进制文件更小,就可以把展开改成中止
- 通过修改cargo.toml文件[profile.release]
- panic='about'
2、panic!宏的使用
1、panic!可能出现的地方
- 自己编写代码中
- 调用的依赖的代码中
2、可以通过panic!宏来回溯出现问题的代码
3、可以通过环境变量设置调试信息
4、在调试的时候,cargo run 必须不能使用--release
fn main() {
panic!("出现错误了");
}
3、可恢复的错误
1、Result<T,E>枚举
enum Result<T,E>{
Ok(T),
Err(E),
}
// T : 表示操作成功的情况,OK变体里返回的数据的类型
// E : 表示操作失败的情况,Err变体里返回的错误的类型
use std::fs::File;
fn main() {
// 这个返回的值就是Resule枚举类型
let f = File::open("1.txt");
}
4、处理Result枚举的结果,使用match
use std::fs::File;
fn main() {
// 这个返回的值就是Resule枚举类型
let f = File::open("1.txt");
// 处理结果
match f {
Ok(file) => file,
Err(err) => panic!(
"打开文件失败{:?}",{err})
};
}
- 匹配不同的错误使用kind()方法,但是里面会嵌套多个match,由此引出了unwrap
- unwrap : match表达式的一个快捷方法
let f = File::open("1.txt").unwrap();
- 但是unwrap不能自定义错误信息,所以引出了另一个方法expect
let f = File::open("1.txt").expect("无法打开文件");
5、传播错误
?运算符:用来传播错误的一种快捷方式
- 后面加?直接就类似于执行了match里面的操作
- 如果result是OK,OK中的值就是表达式的结果,继续执行程序
- 如果result是Err, Err就是整个函数的返回值,就像使用了return
- ?运算符只能作用返回结果为Result才可以使用
fn read_username_from_file() -> Result<String,io::Error>{ // 打开文件 后面加?直接就类似于执行了match里面的操作 let mut f = File::open("1.txt")?; // 创建一个字符串 let mut s = String::new(); f.read_to_string(&mut s)?; Ok(s) }
6、总体原则
1、在定义一个可能失败的函数的时候,优先考虑返回的是Result
2、否则就panic!
推荐阅读: