Error handling 传播不同错误类型的函数的结果类型的正确错误部分是什么?

Error handling 传播不同错误类型的函数的结果类型的正确错误部分是什么?,error-handling,rust,Error Handling,Rust,我试图编写一个函数,它将传播不同的错误类型。仅举个例子,请参见以下代码: use std::fs::File; use std::io; use std::io::Read; fn main() { let number = read_number_from_file().unwrap(); println!("Read number {}!", number); } // So what is the correct error part of the Result<

我试图编写一个函数,它将传播不同的错误类型。仅举个例子,请参见以下代码:

use std::fs::File;
use std::io;
use std::io::Read;

fn main() {
    let number = read_number_from_file().unwrap();

    println!("Read number {}!", number);
}

// So what is the correct error part of the Result<i32, ...>?
fn read_number_from_file() -> Result<i32, io::Error> {
    let mut f = File::open("hello.txt")?;
    let mut s = String::new();
    f.read_to_string(&mut s)?;
    let number = s.parse()?;
    Ok(number)
}
使用std::fs::File;
使用std::io;
使用std::io::Read;
fn main(){
让number=从\文件()中读取\编号\展开();
println!(“读取编号{}!”,编号);
}
//那么,结果的正确错误部分是什么呢?
fn从\u文件()读取\u编号\u->结果{
让mut f=File::open(“hello.txt”)?;
让mut s=String::new();
f、 读取到字符串(&M)?;
设number=s.parse()?;
Ok(号码)
}
编译它会导致以下错误,这并不奇怪:

error[E0277]:`?`无法将错误转换为`std::io::error'`
-->src\main.rs:16:27
|
16 | let number=s.parse()?;
|^std::io::Error未实现特性“std::convert::From”`
|
=注意:问号操作(`?`)使用`From`特性隐式地对错误值执行转换
=帮助:找到了以下实现:
=注意:`std::convert::From::From'需要`

那么
结果的正确错误类型是什么?是否不仅针对这种特定情况有答案:我有一个函数,它多次调用其他函数,返回
结果
,在错误情况下,该结果应从函数传播到调用方,但具有不同的类型
E

您应该定义自己的错误类型,其中包括所有可能发生的错误:

#[derive(Debug)]
enum Error {
    Io(io::Error),
    ParseInt(num::ParseIntError)
}

impl From<io::Error> for Error {
    fn from(other: io::Error) -> Error {
        Error::Io(other)
    }
}

impl From<num::ParseIntError> for Error {
    fn from(other: num::ParseIntError) -> Error {
        Error::ParseInt(other)
    }
}

请注意,这也会生成
显示
实现,我没有在上面介绍。

您应该定义自己的错误类型,其中包括所有可能发生的错误:

#[derive(Debug)]
enum Error {
    Io(io::Error),
    ParseInt(num::ParseIntError)
}

impl From<io::Error> for Error {
    fn from(other: io::Error) -> Error {
        Error::Io(other)
    }
}

impl From<num::ParseIntError> for Error {
    fn from(other: num::ParseIntError) -> Error {
        Error::ParseInt(other)
    }
}

请注意,这也会生成
显示
实现,我在上面没有包括这些实现。

当然,还有另一个使用动态类型的解决方案。只需使用
结果
作为输出即可。然而,彼得·霍尔的答案正是我想要的。谢谢大家!@HBex-供将来参考:标题为“重命名错误以防止与'thiserror::Error'或'std::Error::Error'混淆。还添加了缺少的实现,因此ReadNumberFromFileError是真正的错误类型”;这篇编辑的本意是针对这篇文章的作者,作为编辑毫无意义。它本应作为注释或答案编写。snafu概念将成为您的库API的一部分。-事实不应如此。事实上,SNAFU提供了一个专门的解决方案,以确保您不会泄露实现细节。只需使用
结果
作为输出即可。然而,彼得·霍尔的答案正是我想要的。谢谢大家!@HBex-供将来参考:标题为“重命名错误以防止与'thiserror::Error'或'std::Error::Error'混淆。还添加了缺少的实现,因此ReadNumberFromFileError是真正的错误类型”;这篇编辑的本意是针对这篇文章的作者,作为编辑毫无意义。它本应作为注释或答案编写。snafu概念将成为您的库API的一部分。-事实不应如此。事实上,SNAFU提供了一个专门的方法来确保您不会泄露实现细节。