Rust panic

错误处理

其他语言使用了异常处理来处理错误,但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!

  1. 在定义一个可能失败的函数时,优先考虑返回Result。
  2. 不可恢复的就是panic!
  3. 损坏状态。

为验证创建自定义类型

创建新的类型,把验证逻辑放在构造实例的函数里。(检查器)

#[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)
}
上一篇:Linux Hung Task分析【转】


下一篇:Go错误和异常