如何手动返回结果>?

问题描述 投票:2回答:3

我希望在条件为真的情况下从函数返回错误:

use std::error::Error;

pub fn run() -> Result<(), Box<Error>> {
    // -- snip ---

    if condition {
        // return error
    }

    // -- snip --

    Ok(())
}

fn main() {}

我可能没有类型系统的基础知识,但我看到的每个人都使用?运算符,所以我无法弄清楚要返回的类型。

  1. 是否可以像这样返回错误?
  2. 有没有更好的方法来处理这种逻辑?
error-handling rust type-systems
3个回答
7
投票

Error是一个特征,你想要返回一个特征对象(注意dyn keyword),所以你需要实现这个特性:

use std::error::Error;
use std::fmt;

#[derive(Debug)]
struct MyError(String);

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "There is an error: {}", self.0)
    }
}

impl Error for MyError {}

pub fn run() -> Result<(), Box<dyn Error>> {
    let condition = true;

    if condition {
        return Result::Err(Box::new(MyError("Oops".into())));
    }

    Ok(())
}

fn main() {
    if let Err(e) = run() {
        println!("{}", e); // "There is an error: Oops"
    }
}

我建议你使用failure删除所有错误样板:

#[derive(Fail, Debug)]
#[fail(display = "There is an error: {}.", _0)]
struct MyError(String);

--

请注意,如果你期望一个Error,你可以返回你想要的任何类型,因为它实现了Error。这包括std中的错误类型。


1
投票

Result<T, E>是一个有两个变体的枚举。要返回其中任何一个,只需使用相应的变体即可。

fn foo(var: bool) -> Result<(), i32> {
    if var {
        Ok(()) //in fact this is std::result::Result::Ok
    } else {
        Err(-3) //in fact this is std::result::Result::Err
    }
}

你不必写std::result::Result::Ok的原因是它在prelude。如您所见,您不必坚持使用Box<Error>,但可以返回您想要的任何类型。它是一个通用的枚举,没有任何限制。

?-operator是一个handy shortcut for early returns,因此你不必对结果过于冗长。


1
投票

我是Rust的新手,但是这是我的脏黑客返回自定义错误,因为该函数设置为返回Result<(), Box<dyn Error>>

fn serve(config: &Config, stream: TcpStream) -> Result<(), Box<dyn Error>> {
    // ...
    if request_is_bad() {
        // This returns immediately a custom "Bad request" error
        Err("Bad request")?;
    }
    // ...
}
© www.soinside.com 2019 - 2024. All rights reserved.