type
status
date
slug
summary
tags
category
icon
password
🔔
Prelude: 在写 rust 程序时,Result 和 Option 几乎是我们无法避开的数据结构。我认为比起理解它们的运作机制,首先得迅速搞清楚可以怎么“料理”它们。

礼物的包装

其实不需要把 Option<T>Result<T,E> 想得太复杂:
  • Option 装着我们想要的数据,数据的类型是 T 。不过,里面也有可能没有数据(None)。但无论如何,只要我们关心的东西被包装着,它们都会是 Option
  • Result 也装着我们想要的数据,不过,它还附带了另一个“蠢蠢欲动”的附加项 E (Error)。实际上,Result 和 Option 的组合非常频繁,例如 Result<Option<T>, E>Result 为 Rust 的错误处理提供了强大且统一的规范。

那么,我们该怎么打开礼物盒呢……

拆礼物的时刻总是令人兴奋。
无论是 Option 还是 Result,我们都可以用 unwrap() 来打开这个包裹。
  • 如果礼物盒里装的是正常的值,一切顺利,皆大欢喜。
  • 但如果里面装的是“怪东西”(NoneErr),程序就会立刻 panic 崩溃。
当然,如果坚持使用更安全的开箱方式(比如 unwrap_ormatch 等),就能自己掌控程序是否会崩溃,这非常实用。

礼物盒都提供了哪些功能?

让我们快速过一遍它们提供的方法。详细的解释就不在这里提供了,相信你们能通过 https://doc.rust-lang.org/std/option/https://doc.rust-lang.org/std/result/ 来查询相关信息。

Option

API
作用
返回值和备注
is_some()
判断是否为 Some
bool
is_none()
判断是否为 None
bool
unwrap()
获取 Some 内部的值,若为 None 则触发 panic
T / panic
unwrap_or(default)
获取值,若为 None 则返回指定的默认值
T / default
unwrap_or_else(f)
获取值,若为 None 则调用闭包 f 返回默认值
T / default
map(f)
若为 Some,则对内部值调用 f,返回新的 Option
Option
and_then(f)
若为 Some,则调用 f ,返回另一个 Option
Option
or(other)
若为 None,则返回参数 other,否则返回自身
None/T
or_else(f)
若为 None,则调用闭包 f 返回一个 Option
Option
as_ref()
Option<T> 转换为内部值的不可变引用 Option<&T>
Option<&T>
as_mut()
Option<T> 转换为内部值的可变引用 Option<&mut T>
Option<&mut T>
ok_or(err)
Some(value) 转换为 Ok(value),而 None 转换为 Err(err)
Result
ok_or_else(f)
同上,但如果是 None 则会调用闭包
Result
expect(str&)
unwrap() 相似,但可以自定义错误消息
T / panic
?
None 时直接返回 None(需在返回类型为 Option 的函数中使用)
T / none
值得注意的方法:
  • map(f) 提供了不需要解包也能操作内部数据的方法,十分常用
  • expect("Hi") 可以在 panic 时显示错误信息,比 unwarp() 更加实用
  • ? 可以极大程度地提高代码的整洁性
  • is_some()is_none() 在做判断时也十分好用
 

Result

比起直观易懂的 OptionResult 看似多带了一个类型会比较“绕”, 但本质上它和 Option 是几乎一致的:如果没拿到值(可能是出错了),应该怎么处理。
API
作用
返回值 / 备注
is_ok()
判断是否为 Ok
bool
is_err()
判断是否为 Err
bool
unwrap()
获取 Ok 内部的值,若为 Errpanic
T / panic
unwrap_or(default)
获取值,若为 Err 则返回默认值
T / default
unwrap_or_else(f)
获取值,若为 Err 则调用闭包 f 返回默认值
T / default
map(f)
若为 Ok,对内部值调用 f,返回新的 Result
Result<U, E>
and_then(f)
若为 Ok,调用 f,返回另一个 Result
Result<U, E>
map_err(f)
若为 Err,对错误调用 f,返回新的 Result
Result<T, F>
or(other)
若为 Err,返回 other,否则返回自身
Result<T, E>
or_else(f)
若为 Err,调用闭包 f 返回 Result
Result<T, E>
as_ref()
转为不可变引用
Result<&T, &E>
as_mut()
转为可变引用
Result<&mut T, &mut E>
ok()
成功值 → Some(value),错误 → None
Option<T>
err()
错误值 → Some(error),成功 → None
Option<E>
?
遇到 Err 提前返回(需在返回 Result 的函数中使用)
T / err
Result 也有:map(f)?,以及好用的 is_ok()is_err()
Result<T, E> 中:
  • T 是成功时返回的值的类型(例如文件内容、计算结果等)。
  • E 是错误时返回的值的类型(例如 std::io::Error、自定义错误枚举等)。
  • 实际上:
    • E 可以是任意类型,没有限制
    • 但是为了能用 ?、方便调试和打印,E 通常要实现 DebugDisplayErrortrait
    • 是的,E 可以是很复杂的类型(携带上下文、提供辅助方法),也可以是非常简单的错误结构。而 Err 只是 Result 用来标记“这是错误分支”的外壳,里面装着 E
 

实例

My first post简而言之的Golang
Loading...