Option类型
在编程中,我们经常会遇到某个值或者某个数据域可能存在,可能不存在;如果存在,它才会包含某个值。在C/C++ 中,一般会使用 NULL 表示不存在这种情况,而 NULL 是很多异常和安全的祸根。Rust 从语言层面就删除了对 NULL 的支持,并在标准库中引入 Option 类型,用于表示上述那种可能存在可能不存在的情况。
Option 类型定义如下,它包含在 prelude 中,可以直接引用。
pub enum Option<T> { None, Some(T), }
Result 类型
一个功能、服务的执行结果分为2类:(1)执行成功,返回执行结果;(2)执行失败,返回失败原因。在传统编程语言中,一般使用同一类型的返回值表示这两类结果,这会容易出现混淆。Rust 标准库引入 Result 类型,它是一个 enum 类型,用不同的枚举值类型表示两类结果。同时,基于Rust enum 类型的优点,将执行结果和失败原因包含在其中。借助特定声明式标记#[must_use] ,在代码没有处理这个结果时,给出编译警告,提供程序员优化代码。
Result 类型定义如下,它包含在 prelude 中,可以直接应用。
enum Result<T, E> { Ok(T), Err(E), }
? 运算符
良好的 Rust 代码,很多时候,函数返回的是 Result 类型,如果每个调用都要处理一次返回值,代码就比较繁琐,很多时候,当调用的子函数返回的是 Err 时,我们只是想把这个 Err 传导到调用者函数,借助 ? 运算符,我们就可以实现这样功能。如果子函数返回的是 Ok 时,函数继续往下走;如果返回的是 Err,函数返回并返回这个 Err,由更上层的调用者负责具体处理 Result。
fn fun1() -> Result<int32, String> { } fn fun2() -> Result<int32, String> { } fn fun1() -> Result<int32, String> { } /// 传统处理方式 fn fun() -> Result<int32, String> { if let Err(e) = fun1() { return Err(e); } if let Err(e) = fun2() { return Err(e); } if let Err(e) = fun3() { return Err(e); } Ok(i) } /// 借助 ? 运算符 fn fun() -> Result<int32, String> { fun1()?; fun2()?; fun3()?; Ok(i) } /// 当然,在更上层的调用函数中,还是需要程序员处理这个Result的。比如 fn main() { // fun() 的调用者 main() 返回值不是 Result,就无法再向上传导了。 // 或者fun() 的调用者需要主动对 Err 做处理时,就不要再直接向上传导。 let ret = fun(); match ret { Ok(i) => { println!("success, ret is {i}"); } Err(e) => { println!("Fail, error reason is {e:}"); } } }
? 运算符同样适用于 Option,当遇到 None 时,直接返回并向上传导。