为什么Rust自定义错误枚举需要Display实现,而我必须格式化输出?

zf9nrax1  于 2023-04-06  发布在  其他
关注(0)|答案(1)|浏览(161)

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

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

此枚举实现了Display trait(根据需要):

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)
            }

在Match中没有格式化文件名和错误,Rust只是打印一般错误(在这种情况下“系统无法找到指定的文件。
我的问题是:如果为了打印/使用它需要再次格式化它,为什么需要首先实现显示和格式化错误?

46qrfjad

46qrfjad1#

不需要再次格式化它。这在你没有使用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}");
}

相关问题