/*
程序中一般会出现两种错误:可恢复错误和不可恢复错误
可恢复错误:可恢复错误的典型案例是文件访问错误,如果访问一个文件失败,有可能是因为它正在被占用,是正常的,我们可以通过等待来解决
不可恢复错误:由编程中无法解决的逻辑错误导致的,例如访问数组末尾以外的位置
对于可恢复错误用 Result<T, E> 类来处理,对于不可恢复错误使用 panic! 宏来处理。
enum Result<T, E> {
Ok(T),
Err(E),
}
在 Rust 标准库中可能产生异常的函数的返回值都是 Result 类型的
*/
use std::fs::File;
use std::io;
use std::io::Read;
fn main() {
//不可恢复错误用法:
//panic!("error occured");
let f = File::open("hello.txt");
match f {
Ok(file) => {
println!("File opened successfully.");
}
Err(err) => {
println!("Failed to open the file.");
}
}
//如果想使一个可恢复错误按不可恢复错误处理,Result 类提供了两个办法:unwrap() 和 expect(message: &str) :
//两者的区别在于 expect 能够向 panic! 宏发送一段指定的错误信息。
let f1 = File::open("hello.txt").unwrap();
let f2 = File::open("hello.txt").expect("Failed to open.");
//测试方法1
let r = myerro(-10000);
if let Ok(v) = r {
println!("Ok: f(-1) = {}", v);
} else {
println!("Err");
}
//测试方法2
println!("{:?}", call_myerro(-101));
//测试方法3
println!("{:?}", call_myerro2(101));
catch_ifreadfile_err();
}
//自定义错误
fn myerro(i: i32) -> Result<i32, bool> {
if i >= 0 {
Ok(i)
} else {
Err(false)
}
}
//测试-自定义错误
fn call_myerro(i: i32) -> Result<i32, bool> {
let t = myerro(i);
return match t {
Ok(i) => Ok(i),
Err(b) => Err(b),
};
}
//call_myerro写有些冗长,Rust 中可以在 Result 对象后添加 ? 操作符将同类的 Err 直接传递出去.
//? 符的实际作用是将 Result 类非异常的值直接取出,如果有异常就将异常 Result 返回出去。所以,?
//符仅用于返回值类型为 Result<T, E> 的函数,其中 E 类型必须和 ? 所处理的 Result 的 E 类型一致
fn call_myerro2(i: i32) -> Result<i32, bool> {
let t = myerro(i)?;
Ok(t)
}
//获取 Err 类型的函数是 kind().实现try catch
//Rust 似乎没有像 try 块一样可以令任何位置发生的同类异常都直接得到相同的解决的语法,但这样并不意味
//着 Rust 实现不了:我们完全可以把 try 块在独立的函数中实现,将所有的异常都传递出去解决
fn read_text_from_file(path: &str) -> Result<String, io::Error> {
let mut f = File::open(path)?;
let mut s = String::new();
f.read_to_string(&mut s)?;
Ok(s)
}
fn catch_ifreadfile_err() {
let str_file = read_text_from_file("hello2.txt");
match str_file {
Ok(s) => println!("{}", s),
Err(e) => match e.kind() {
io::ErrorKind::NotFound => {
println!("No such file");
}
_ => {
println!("Cannot read the file");
}
},
}
}