有没有办法从
Option
中“提取”数据?我有一个返回 Some(HashMap)
的 API 调用。我想使用 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!");
而且,因为你的函数返回一个
Result
:
let origin = resp.get("origin").ok_or("This shouldn't be possible!")?;
或者使用自定义错误类型:
let origin = resp.get("origin").ok_or(MyError::DoesntExist)?;
最常见的方式是用
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();
您可以使用
panic
自定义expect
消息:
let origin = resp.get("origin").expect("Oops!");
或者使用
unwrap_or
计算默认值:
let origin = resp.get("origin").unwrap_or(&String::from("192.168.0.1"));
你也可以返回一个错误而不是恐慌:
let origin = resp.get("origin").ok_or(Error::UnknownOrigin)?;
你的选择很多。
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
})