当我无论如何都必须格式化输出时,为什么 Rust 自定义错误枚举需要实现 Display?

问题描述 投票:0回答:1

我有一个自定义错误枚举,它包含了我代码中的几个常见错误:

pub enum ParseError {
    Io(io::Error),
    Parse(serde_json::error::Error),
    FileNotFound(PathBuf, io::Error),
}

此枚举实现了 Display 特性(按要求):

impl Display for ParseError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ParseError::Io(io_error) => write!(f, "{}", io_error),
            ParseError::Parse(parse_error) => write!(f, "{}", parse_error),
            ParseError::FileNotFound(file, err) => {
                write!(f, "Could not open file {}: {}", file.to_string_lossy(), err)
            }
        }
    }
}

注意,对于“自定义错误”FileNotFound,我需要写!错误和它附带的文件名。但是,稍后当我处理这个错误时,我需要再次打印文件名和错误:

    match my_function(arg1, arg2) {
        Ok(_) => (),
        Err(error) => match error {
            Io(err) => //do stuff,
            },
            Parse(err) => //do stuff
            },
            FileNotFound(file, err) => {
                println!("Can't find file '{}': {}", file.to_string_lossy(), err)
            }

没有格式化文件名和匹配中的错误,Rust 只是打印一般错误(在这种情况下“系统找不到指定的文件。(操作系统错误 2)”。

我的问题是:为什么需要先实现显示和格式化错误,如果需要再次格式化才能打印/使用它?

rust error-handling typetraits
1个回答
0
投票

不需要重新格式化。当您不使用

match
时,这特别有用,但是当您这样做时,您可以使用
@
创建对整个项目的绑定:

match my_function(arg1, arg2) {
    Ok(_) => (),
    Err(error) => match error {
        Io(err) => { //do stuff,
        }
        Parse(err) => { //do stuff
        }
        error @ FileNotFound(..) => {
            println!("{error}");
        }
    },
}

您还可以就地构建错误:

FileNotFound(file, err) => {
    println!("{}", FileNotFound(file, err));
}

另一个常见的事情是使用 catch-all 对所有不匹配的错误执行操作:

error => {
    println!("{error}");
}
© www.soinside.com 2019 - 2024. All rights reserved.