如何从选项中提取数据以供独立使用?

How can I pull data out of an Option for independent use?

有没有办法从 Option 中提取 'pull' 数据?我有一个 API 调用 returns Some(HashMap)。我想使用 HashMap 就好像它不在 Some 中一样,并使用数据。

根据我的阅读,Some(...) 似乎只适用于匹配比较和一些内置函数。

简单的 API 从板条箱文档中提取的调用:

use std::collections::HashMap;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let resp = reqwest::blocking::get("https://httpbin.org/ip")?
        .json::<HashMap<String, String>>()?;
    println!("{:#?}", resp.get("origin"));
    Ok(())
}

结果:

Some("75.69.138.107")
if let Some(origin) = resp.get("origin") {
    // use origin
}

如果你能保证这个值不可能是None,那么你可以使用:

let origin = resp.get("origin").unwrap();

或者:

let origin = resp.get("origin").expect("This shouldn't be possible!");

而且,由于你的函数 returns a Result:

let origin = resp.get("origin").ok_or("This shouldn't be possible!")?;

或使用自定义错误类型:

let origin = resp.get("origin").ok_or(MyError::DoesntExist)?;

你的选择很多。

if let Some(origin) = resp.get("origin") {
    // do stuff using origin
}
origin = resp.get("origin").unwrap()
// will panic if None
resp.get("origin").map(|origin| {
    // do stuff using inner value, returning another option
})
resp.get("origin").and_then(|origin| {
    // same as map but short-circuits if there is no inner value
})

最常见的方式是 if let:

if let Some(origin) = resp.get("origin") {
    origin.do_stuff()
}

为了更细粒度的控制,可以使用模式匹配:

match resp.get("origin") {
    Some(origin) => origin.do_stuff(),
    None => panic!("origin not found!")
}

您也可以使用 unwrap,这将为您提供期权的基础价值,或者 panic 如果它是 None:

let origin = resp.get("origin").unwrap();

您可以使用 expect 自定义 panic 消息:

let origin = resp.get("origin").expect("Oops!");

或者用unwrap_or计算默认值:

let origin = resp.get("origin").unwrap_or(&String::from("192.168.0.1"));

您也可以 return 一个错误而不是恐慌:

let origin = resp.get("origin").ok_or(Error::UnknownOrigin)?;