如何正确使用Result?

How to use Result correctly?

我正在尝试 return 如果一切顺利,如果出现问题,return 错误代码,但它不起作用:

mod reader {
    /*uses*/
    enum FileError {
        FileNotFound,
        PgnInvalid,
    }
    fn read_game(file_path: &str) -> Result<BufferedReader<File>, FileError> {
        let f = File::open(file_path)?;
        match f {
            Err(e) => FileError::FileNotFound,
            Ok(file) => {
                let r = BufferedReader::new(file)?;
                match r {
                    Err(e) => FileError::PgnInvalid,
                    Ok(reader) => reader,
                }
            }
        }
    }
}

我收到这个错误:

 mismatched types [E0308] expected `Result<BufferedReader<File>, FileError>`, found `FileError` 

Result 是一个枚举,它可以是以下两种变体之一:Ok(..)Err(..)。当 returning 一个结果时,您需要指定您 returning 的变体。现在你只是 returning FileErrorBufferedReader<File> 导致匹配武器的类型冲突,并且还与 return 类型冲突。相反,您可以做的是使用 Resultmap_err 函数映射错误类型,并将 ?(读作“try”)运算符早期应用于 return 错误遇到错误时的变体。

fn read_game(file_path: &str) -> Result<BufferedReader<File>, FileError> {
    let f = File::open(file_path).map_err(|_| FileError::FileNotFound)?;
    BufferedReader::new(f).map_err(|_| FileError::PgnInvalid)
}

您可以在有关枚举的书中阅读有关结果 here, and I'd also recommend checking out the section 的更多信息。

要return一个Result,您需要return它的枚举值之一,OkErr。所以你的代码可能是:

fn read_game(file_path: &str) -> Result<BufferedReader<File>, FileError> {
    let f = File::open(file_path);
    match f {
        Err(e) => Err(FileError::FileNotFound),
        Ok(file) => {
            let r = BufferedReader::new(file);
            // BufferedReader::new does not return a `Result`.
            // Wrap the reader in `Ok` to return a `Result`.
            Ok(r)
        }
    }
}

作为快捷方式,? 运算符会为您解包任何 Ok 值和 returns 任何 Err 值。所以你可以添加 ? 并删除 match 以获得这个几乎可以工作的代码:

fn read_game(file_path: &str) -> Result<BufferedReader<File>, FileError> {
    let f = File::open(file_path)?;
    let r = BufferedReader::new(file);
    Ok(r)
}

此代码的问题是 returned Result 不支持 std::io::Error(来自 open 的错误类型)。您可以 return a Result<BufferedReader<File>, std::io::Error> 或者您可以将错误类型映射到您支持的类型:

fn read_game(file_path: &str) -> Result<BufferedReader<File>, FileError> {
    let f = File::open(file_path).map_err(|_| FileError::FileNotFound)?;
    let r = BufferedReader::new(f);
    Ok(r)
}