简体   繁体   English

即使出现 function 错误,我该如何继续?

[英]How do I continue even when a function errors?

I'm using reqwest and scraper to write a simple web scraper in rust.我正在使用reqwestscraper在 rust 中编写一个简单的 web 刮板。 One section of my code is given a link "next_page" that may or may not be valid.我的代码的一部分给出了一个链接“next_page”,它可能有效也可能无效。 I want to try to access the link, and if there's an error, print the error and continue to the next link.我想尝试访问链接,如果有错误,打印错误并继续下一个链接。 Here's what I tried to do:这是我试图做的:

let next_page_response = reqwest::get(next_page).await;
let next_page_response = match next_page_response {
    Ok(response) => response,
    Err(error) => println!("WARN: Problem getting the url '{}'. \
        The error was {:?}", next_page, error),
};

This code is wrapped in a loop, and next_page changes every iteration.这段代码被包裹在一个循环中,并且next_page每次迭代都会改变。

This doesn't work, rustc gives the error error[E0308]: 'match' arms have incompatible types .这不起作用, rustc给出错误error[E0308]: 'match' arms have incompatible types I suppose this makes sense, in the first arm the expression becomes a Response , whereas in the second arm it becomes a () .我想这是有道理的,在第一个 arm 中,表达式变成了Response ,而在第二个 arm 中,它变成了() However, if I change println!但是,如果我改变println! to panic! panic! , the code compiles. ,代码编译。

Questions:问题:

  1. How can I acknowledge an error and then just continue?如何确认错误然后继续?
  2. Why does panic!为什么会panic! work when println! println! doesn't?不是吗?

Full code, for the curious .完整的代码,对于好奇的.

As you allude to in the original post, the issue is that the return values of the two branches don't match.正如您在原始帖子中提到的那样,问题在于两个分支的返回值不匹配。 And as kmdreko mentions panic!正如 kmdreko 提到的panic! works since it has a return type that can be used anywhere.之所以有效,是因为它具有可以在任何地方使用的返回类型。

So if you want to avoid the panic you need to make the return values from each branch match.因此,如果您想避免恐慌,您需要使每个分支的返回值匹配。

One way is to have both arms return () .一种方法是让双臂返回() The code can be pretty simple if you put the processing of the successful response into the body of the match.如果您将成功响应的处理放入匹配的正文中,则代码可以非常简单。

pub fn process_response(response: &Response) {
    // ...
}

for next_page in pages {
    let next_page_response = reqwest::get(next_page).await;
    match next_page_response {
        Ok(response) => process_response(response),
        Err(error) => println!("WARN: Problem getting the url '{}'. \
             The error was {:?}", next_page, error),
    };
}

An alternate is to have both arms return an Option that you use later.另一种方法是让双臂返回一个稍后使用的Option (In this case, it makes the code longer and uglier in my opinion, but there can be cases where it is useful). (在这种情况下,我认为它会使代码更长更丑,但在某些情况下它可能很有用)。 It could look something like this:它可能看起来像这样:

pub fn process_response(response: &Response) {
    // ...
}

for next_page in pages {
    let next_page_response = reqwest::get(next_page).await;
    let next_page_response = match next_page_response {
        Ok(response) => Some(response),
        Err(error) => {
             println!("WARN: Problem getting the url '{}'. \
                 The error was {:?}", next_page, error);
             None
        }
    };

    if let Some(response) = next_page_response {
        process_response(response)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM