您能否返回适用于任何可能的错误类型的结果?

rap*_*ock 8 error-handling rust

我想使用多个库,每个库都有自己的错误类型。我并不真正关心每个特定板条箱的错误类型,我想使用?习惯用法来使用那些返回类型的板条箱的方法Result

我也不想解开这些值,如果遇到错误,这会导致恐慌。我可能只是想将不同的错误传播?到顶部,并且如果我愿意的话,也许可以选择处理它们或忽略它们。

我不能用 a 做到这一点,std::result::Result<T, E>因为我不知道返回的错误类型(就像我说的,每个板条箱都可以返回自己的错误)。

我知道 Rust 中没有“面向对象”的多态性,但有特征对象。由于在编译时无法知道特征对象的大小,因此我们必须将它们隐藏在某种指针后面,例如&or Box<_>

错误实现的基本特征似乎是std::error::Error

我看到的一件事是fn foo() -> Result<Blah, Box<dyn Error>>策略,它利用了特征对象的概念。

这种策略的问题是没有一个包返回装箱错误,这导致编译器抱怨同样的问题。

一个示例用例:

use native_tls::TlsConnector; // 0.2.3
use std::io::{Read, Write};
use std::net::TcpStream;

fn main() {
    match do_stuff() {
        Ok(string) => {
            println!("{}", string);
        }
        _ => {
            println!("Failed!");
        }
    }
}

fn do_stuff() -> Result<String, Box<(dyn std::error::Error + 'static)>> {
    let connector = TlsConnector::new()?;

    let stream = TcpStream::connect("jsonplaceholder.typicode.com:443")?;
    let mut stream = connector.connect("jsonplaceholder.typicode.com", stream)?;

    stream.write_all(b"GET /todos/1 HTTP/1.0\r\n\r\n")?;
    let mut res = vec![];
    stream.read_to_end(&mut res)?;
    String::from_utf8(res)
}
Run Code Online (Sandbox Code Playgroud)

操场

有一个简单的方法可以解决这个问题吗?我可以轻松地抽象出所有不同的错误并返回 aResult以便我可以使用该?习惯用法吗?

She*_*ter 1

您能否返回适用于任何可能的错误类型的结果?

你不能。从表面上看,这没有道理。泛型类型是由函数的调用者选择的,那么函数如何在不被告知如何构造它的情况下创建由其他人选择的错误呢?


也就是说,你的问题很容易解决。你说:

所以我可以使用这个?习语

如果您始终如一地这样做,您的程序将编译:

let s = String::from_utf8(res)?;
Ok(s)
Run Code Online (Sandbox Code Playgroud)

您还可以直接转换错误类型:

String::from_utf8(res).map_err(Into::into)
Run Code Online (Sandbox Code Playgroud)

没有一个板条箱返回装箱错误,这导致编译器抱怨同样的问题

它不适用于您使用过的其他5?种情况,因此不清楚您为何做出此声明。

具体来说,Box<dyn Error>可以从任何实现以下类型的类型创建Error

impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
    fn from(err: E) -> Box<dyn Error + 'a> {
        Box::new(err)
    }
}
Run Code Online (Sandbox Code Playgroud)

接线员在后台?呼叫您。From::from

也可以看看: