Rust 第14节 错误处理
默认情况,当程序发生panic时,
1)程序展开调用栈(工作量大)
Rust沿着调用栈往回走
清理遇到的每一个函数的数据
2)或立即中止调用栈
不进行清理,直接停止程序
内存需要0S进行清理
想让二进制更小,把设置从“展开”改为 “中止”
在Cargo.toml中适当的profile 中进行设置
panic = ‘abort’
[profile.release]
panic = 'abort'
主动触发错误
使用panic! 宏
panic!("error ;crash and return"); //程序执行到这里就会直接挂掉
Result枚举
Result枚举结果如下:
enum Result<T,E>{
Ok<T>, //操作成功时,返回的数据为T
Err<E>
}
当成功时,数据保存在Ok中,当失败时,返回Err,并带回错误信息;
Result 也在预导入模块就导入了,可以直接使用Ok,Err
例子:
let f = File::open("test.txt"); //open 就返回一个 result 类型的数据
let f = match f {
Ok(filename) =>{
filename //成功,返回该文件
},
Err(e) => {
panic!("open err is {:?}",e) //错误直接自杀
}
};
优化:
let f = File::open("test.txt");
let f = match f {
Ok(file) => {
file
},
Err(error) =>
{ //对报错的ID继续判断
match error.kind() {
ErrorKind::NotFound => {//没有找到的ID
let new = File::create("test.txt");
match new {
Ok(filename2) => filename2,
Err(err) => panic!("create new file error:{:?}",err),
}//创建一个新的并返回
},
_ => {
panic!("其他错误");
},
}
},
};
unwrap()方法
unwrap()方法能自动做到解析返回的Result类型,如果是Ok,则取出其中的数据,返回;如果是Err,直接自杀
let f = File::open("HELLO.txt").unwrap();//成功返回OK中的值,失败调用panic!()
unwrap()很好用,但是无法自定义报错信息,这时就有了更好用的expect();
expect() 方法
expect方法在unwrap()方法的基础上;增加了自定义报错信息。
let f = File::open("HELLO.txt").expect("打开文件失败");//成功返回OK中的值,失败调用panic!()
//并打印传入的字符串
传播错误
在大多数情况下,错误发生时,我们并不直接进行自杀,而是将错误传递给调用者;
让调用者自行决定如何处理。
//这个函数的功能是从文件中读取数据
fn read_from_file()-> Result<String,io::Error> {
//这里我们让报错通过返回值返回;OK中保存的是字符串,Err中保存的是标准报错
let mut str = String::new();
let f = File::open("h.txt");
let mut f = match f {
Ok(f) => f,
Err(e) => return Err(e),//这里如果报错,就直接返回,带回报错的数据;这里的e就是io::Error类型
};
match f.read_to_string(&mut str) {
Ok(_) => Ok(str),//这里成功就将数据保存到OK中
Err(e) => Err(e),//失败将失败的数据保存到Err中返回;这里的e就是io::Error类型
}
}
fn main() {
```
let data = read_from_file();
```
}
其实不用如此麻烦,Rust给我们提供了一个简便的运算符 ?
? 运算法功能: 如果调用的返回值为Ok,则将Ok中的数据返回,如果是Err,则直接return Err;
fn read_from_file_v2()-> Result<String,io::Error> {
let mut str = String::new();
let mut f = File::open("h.txt")?; //这里?表示,成功,将成功数据取出返回,错误直接调用return,并将Err()作为函数结果返回
f.read_to_string(&mut str)?;
Ok(str)
}
当然了,我们可以连起来写,更加简便
fn read_from_file_v3()-> Result<String,io::Error> {
let mut str = String::new();
File::open("h.txt")?.read_to_string(&mut str)?;
Ok(str)
}