书接上回: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。
以上应该说清楚了。
相关文章: