使用MongoDB Rust驱动如何便捷访问全为Optional的嵌套结构体数据
Rust 嵌套Option字段取值简化方案
以下为几种可在稳定版Rust中使用的简化写法,默认异常返回值为0:
- 方案1:链式
and_then调用(最通用,无额外依赖)
无需消费原始查询结果可加as_ref转换为引用操作:
// 消费原始数据的写法 let system_id = query_result .ok() // 将Result转为Option,Err场景直接转None .flatten() // 压平两层Option<Option<Device>>为Option<Device> .and_then(|device| device.system) .and_then(|system| system.id) .unwrap_or(0); // 保留原始数据所有权的写法 let system_id = query_result .as_ref() .ok() .flatten() .and_then(|device| device.system.as_ref()) .and_then(|system| system.id) .unwrap_or(0);
- 方案2:多层
if let匹配(可读性强,适合需要添加额外分支逻辑的场景)
let mut system_id = 0; if let Ok(Some(device)) = query_result.as_ref() { if let Some(system) = &device.system { if let Some(id) = system.id { system_id = id; } } }
- 方案3:立即执行闭包 +
?运算符(代码更精简,无需嵌套分支)
let system_id = (|| { let device = query_result.as_ref().ok()??; let system = device.system.as_ref()?; system.id })().unwrap_or(0);
- 方案4:结构体添加辅助方法(适合高频访问该字段的场景,提升复用性)
impl Device { pub fn get_system_id(&self) -> u32 { self.system.as_ref().and_then(|sys| sys.id).unwrap_or(0) } } // 调用示例 let system_id = query_result .as_ref() .ok() .flatten() .map(|dev| dev.get_system_id()) .unwrap_or(0);
如果使用nightly版本Rust,还可以开启try_blocks特性进一步简化写法:
#![feature(try_blocks)] let system_id: u32 = try { let device = query_result.as_ref().ok()??; device.system.as_ref()?.id? }.unwrap_or(0);
内容的提问来源于stack exchange,提问作者JustMark
相关产品推荐
相关产品推荐

