Rust基础-错误处理-自定义错误之二

书接上回:Rust基础-错误处理-自定义错误之一_DarcyZ_SSM的博客-CSDN博客

还存在两个问题

1、match的嵌套太多代码可读性太差。

2、error的返回每次都要转换,无法标准化。

对于第一个问题可以用以下这个宏来解决

macro_rules! try {
    ($e:expr) => (match $e {
        Ok(val) => val,
        Err(err) => return Err(::std::convert::From::from(err)),
    });
}

对于第二个问题,标准化错误返回的问题,Rust普遍采用Box<Error>的方式传递。

impl<'a, E: Error + 'a> From<E> for Box<Error + 'a>

并且在现在的版本Rust加入了?操作符,用来替代try!

那么完整的代码如下

use std::fmt;
use std::fs::File;
use std::io::{self, Read};
use std::{error, num};
use std::error::Error;

#[derive(Debug)]
struct AppError {
    kind: String,
    message: String,
}

impl fmt::Display for AppError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self.kind as &str {
            "404" => write!(
                f,
                "程序出错:{{错误类型: {}, 错误原因: {}}}",
                self.kind, self.message
            ),
            _ => write!(f, "Sorry, something is wrong! Please Try Again!"),
        }
    }
}
// impl fmt::Debug for AppError {
//     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//         write!(
//             f,
//             "AppError {{ 错误类型: {}, 错误原因: {} }}",
//             self.kind, self.message
//         )
//     }
// }

impl error::Error for AppError {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
         Some(self)
    }
}

impl From<io::Error> for AppError {
    fn from(error: io::Error) -> Self {
        AppError {
            kind: String::from("io"),
            message: error.to_string(),
        }
    }
}

impl From<num::ParseIntError> for AppError {
    fn from(error: num::ParseIntError) -> Self {
        AppError {
            kind: String::from("parse"),
            message: error.to_string(),
        }
    }
}
fn produce_error() -> Result<(), AppError> {
    Err(AppError {
        kind: String::from("404"),
        message: String::from("Page not found"),
    })
}

 fn do_job() -> Result<(),AppError>{
    //produce_error()?;
    let mut content = String::new();
    let mut file = File::open("./hello_world.txt")?;
    file.read_to_string(&mut content)?;
    let number=content.parse::<u32>()?;
    println!("{:#?}", number);
    Ok(())
}
fn main() -> Result<(), Box<dyn Error>>
{
    do_job()?;
    Ok(())
}

做一下解释:

1、在do_job() -> Result<(),AppError>{ ... } 这个函数内是自定义错误的边界,所有做过自定义转换过的Error都应该是Result<(),AppError>这样的签名的函数内调用。

2、impl error::Error for AppError 这个trait是为了将AppError转换为Box<dyn Error>>,这样所有的自定义错误就能被标准错误类型所输出。

3、最后,还要实现impl fmt::Display for AppError,就是将AppError以自定义的形式输出。当然也可以自定义实现impl fmt::Debug for AppError。

以上应该说清楚了。

相关文章:

Rust基础-错误处理-自定义错误之一_DarcyZ_SSM的博客-CSDN博客

Rust基础-错误处理-自定义错误之三-snafu方案_DarcyZ_SSM的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值