这里不复述文档和教程中有的内容, 比如Result之类的细节, 可以自行看文档内容:
参考资料: https://www.philipdaniels.com/blog/2019/defining-rust-error-types/
 1. Rust中自定义Error的方式
 1.1 定义一个错误类型:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | #[derive(Debug)]pub enum MyErorType {
 
 Io(io::Error),
 Git(git2::Error),
 
 Regular(ErrorKind),
 Custom(String)
 }
 
 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
 pub enum ErrorKind {
 NotFound,
 NotAuthorized,
 
 }
 
 impl ErrorKind {
 fn as_str(&self) -> &str {
 match *self {
 ErrorKind::NotFound => "not found",
 ErrorKind::NotAuthorized => "not authorized"
 }
 }
 }
 
 | 
 1.2 实现Error和Display这两个trait
Error只允许返回静态字符串常量
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | impl Error for MyErrorType {fn description(&self) -> &str {
 match *self {
 MyErrorType::Io(ref err) => err.description(),
 MyErrorType::Git(ref err) => err.description(),
 MyErrorType::Regular(ref err) => err.as_str(),
 MyErrorType::Custom(ref err) => err,
 }
 }
 }
 
 | 
fmt::Display更为灵活一点
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | impl fmt::Display for MyErrorType {fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 match *self {
 MyErrorType::Io(ref err) => err.fmt(f),
 MyErrorType::Git(ref err) => err.fmt(f),
 MyErrorType::Regular(ref err) => write!(f, "A regular error occurred {:?}", err),
 MyErrorType::Custom(ref err) => write!(f, "A custom error occurred {:?}", err),
 }
 }
 }
 
 | 
 1.3 为external error type实现From
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | impl From<io::Error> for MyErrorType {fn from(err: io::Error) -> MyErrorType {
 MyErrorType::Io(err)
 }
 }
 
 impl From<io::Error> for MyErrorType {
 fn from(err: git2::Error) -> MyErrorType {
 MyErrorType::Git(err)
 }
 }
 
 | 
使用起来就可以这样, 在捕获异常的代码片段中:
 1.4 可选: 创建一个Result别名
| 1
 | pub type Result<T> = std::result::Result<T, MyErrorType>;
 | 
 1.5 使用自定义的类型:
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | fn some_func() -> Result<usize> {
 let _f = std::fs::File::create("aa")?;
 
 let _g = Respository::init("/path/to/repo")?;
 
 
 Err(MyErrorType::Regular(ErrorKind::NotAuthorized));
 }
 
 | 
 2. Rust 中使用 thiserror 和 anyhow (简洁, 好用)
thiserror文档: https://docs.rs/thiserror/latest/thiserror/
anyhow文档: https://github.com/dtolnay/anyhow
这两个库主要还是为了某些库里处理数量众多的异常类型, 可以解决兼容, 但还需要额外处理
| 12
 3
 4
 5
 6
 
 | use anyhow::Result
 fn get() -> Result<()> {
 
 }
 
 
 | 
 3. 错误类型映射
前面所作的努力只是为了兼容, 但是rust并不会主动去做, 转换工作还是得自己来
 3.1 map_err
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | use std::env;
 fn double_arg(mut argv: env::Args) -> Result<i32, String> {
 argv.nth(1)
 .ok_or("Please give at least one argument".to_owned())
 .and_then(|arg| arg.parse::<i32>().map_err(|err| err.to_string()))
 .map(|n| 2 * n)
 }
 
 fn main() {
 match double_arg(env::args()) {
 Ok(n) => println!("{}", n),
 Err(err) => println!("Error: {}", err),
 }
 }
 
 | 
| 12
 3
 4
 5
 
 | cmdline.insert_str(boot_args)
 .map_err(BootSourceConfigError::InvalidKernelCommandLine)
 .map_err(VmmActionError::BootSource)
 .map_err(CLIError::BootSource)?;
 
 |