错误处理
其他语言使用了异常处理来处理错误,但rust里没有。rust把错误分成了可恢复/不可恢复。
可恢复错误
Result<T, E>
Result<T, E>枚举类型来处理可恢复错误。
- T返回数据的操作类型
- E返回错误的操作类型。
Result是与导入模块。使用match去匹配。
匹配不同的错误
use std::fs::File;
use std::io::ErrorKind;
fn main() {
let f = File::open("account.txt");
let f = match f {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("account.txt") {
Ok(fc) => fc,
Err(e) => panic!("error: {:?}", e),
},
otherError => panic!("unknow error: {:?}", otherError),
}
};
}
unwarp
unwarp(); match的快捷表达。
如果result的结果是Ok, 返回Ok里面的值。如果reuslt结果是err,调用panic!宏。这个错误信息不能自定义,但是可以expect。
unwarp()打印的都是同样的错误信息。
let f = File::open("hello.txt").unwrap();
expect
自定义错误信息。
let f = File::open("hello.txt").expect("File not for found.");
传播错误
错误可以在函数内处理,也可以返回给这个函数的调用者,让调用者决定如何处理。
use std::fs::File;
use std::io::{self, ErrorKind};
use std::io::Read;
fn readSomething() -> Result<String, io::Error> {
let f = File::open("account.txt");
let mut f = match f {
Ok(file) => file,
// 这里就 return 结束了
Err(e) => return Err(e),
};
let mut s = String::new();
match f.read_to_string(&mut s) {
Ok(ok) => Ok(s),
Err(e) => Err(e),
}
}
fn main() {
let result = readSomething();
print!("{:?}", result)
}
? 运算符
如果result前面的值是正确的就返回,程序继续执行;错误的就返回错误(return 结束了)。
let f = File::open("account.txt")?;
加?返回错误,返回的错误类型是函数所定义返回的错误。
链式调用
use std::fs::File;
use std::io::{self, ErrorKind};
use std::io::Read;
fn readSomething() -> Result<String, io::Error> {
let mut s = String::new();
let f = File::open("account.txt")?.read_to_string(&mut s)?;
Ok(s)
}
fn main() {
let result = readSomething();
print!("{:?}", result)
}
Q: ? 运算符只能用于返回result的函数。
A: 返回一个Result<(), Box
from
有from函数的才能用?
针对不同的错误原因,返回同一种错误类型。只要每个错误类实现了转换为所返回的错误类型的from函数。
不可恢复
paninc! 宏
当这个宏执行的时候:打印清理一个错误信息,展开,清理或中止调用栈,崩溃。
默认情况下,painc发生时:展开调用栈或中止调用栈。
设置中止调用栈:Cargo.toml -> panic = 'abort'
显示调用栈(回溯信息):
设置环境变量 RUST_BACKTRACE = 1,--release版本下不能使用。
何时用panic!
- 在定义一个可能失败的函数时,优先考虑返回Result。
- 不可恢复的就是panic!
- 损坏状态。
为验证创建自定义类型
创建新的类型,把验证逻辑放在构造实例的函数里。(检查器)
#[derive(Debug)]
struct Guess{
value: i32,
}
impl Guess{
fn check(value: i32) -> Guess {
if value > 5 {
panic!("error number")
}
Guess{ value }
}
}
fn main() {
let result = Guess::check(5);
print!("{:?}", result)
}