Rust Option Result 的快捷使用技巧

前言

在 Rust 中,有两个非常常用的枚举类型:OptionResult。它们替代了其他语言中的 null 和异常机制,是 Rust 类型安全的基础。本文总结这两个类型在业务逻辑中的常用方法。

Option

Option 官方文档地址: enum.Option

Option 的定义如下:

1
2
3
4
pub enum Option<T> {
None,
Some(T),
}

Option 方法速查

分类 方法 说明
判断 is_some() / is_none() 判断是 Some / None
判断 is_some_and(f) / is_none_or(f) Some 且满足条件 / None 或不满足条件
提取 unwrap() / expect(msg) 解包,失败时 panic
提取 unwrap_or(v) / unwrap_or_else(f) 解包或提供默认值
提取 unwrap_or_default() 解包或使用 Default
转换 map(f) / inspect(f) 对值应用函数 / 执行副作用
转换 map_or(v, f) / map_or_else(f, g) 转换或提供默认值
链式 and(opt) / and_then(f) Some 时继续链式调用
链式 or(opt) / or_else(f) None 时回退备选值
链式 xor(opt) 异或组合
过滤 filter(f) 不满足谓词则变 None
引用 as_ref() / as_mut() 转为引用的 Option
引用 as_deref() / as_deref_mut() 解引用引用
引用 cloned() / copied() Option<&T>Option<T>
插入 insert(v) / get_or_insert(v) 插入值并返回引用
插入 get_or_insert_with(f) / get_or_insert_default() 惰性插入值
取出 take() / take_if(f) 取出值并将自身置 None
替换 replace(v) 替换值并返回旧值
组合 zip(other) / zip_with(other, f) 组合两个 Option
组合 unzip() Option<(A,B)>(Option<A>, Option<B>)
展开 flatten() / transpose() 嵌套展开
迭代 iter() / iter_mut() 转为迭代器
切片 as_slice() / as_mut_slice() 转为切片
互转 ok_or(e) / ok_or_else(f) Result

Option 查询变体(条件判断)

is_some() -> bool - 判断是否为 Some

1
2
3
4
5
let x: Option<u32> = Some(2);
assert!(x.is_some());

let y: Option<u32> = None;
assert!(!y.is_some());

is_some_and(f) -> bool - 为 Some 且闭包函数返回 true则返回 true(1.70+)

1
2
3
let x: Option<u32> = Some(2);
assert!(x.is_some_and(|x| x > 1));
assert!(!x.is_some_and(|x| x > 2));

is_none() -> bool - 判断是否为 None

1
2
3
4
5
let x: Option<u32> = Some(2);
assert!(!x.is_none());

let x: Option<u32> = None;
assert!(x.is_none());

is_none_or(f) -> bool - 为 None 或闭包函数返回 true则返回 true(1.82+)

1
2
3
4
5
6
7
8
let x: Option<u32> = None;
assert!(x.is_none_or(|x| x > 1));

let x: Option<u32> = Some(2);
assert!(x.is_none_or(|x| x > 1));

let x: Option<u32> = Some(0);
assert!(!x.is_none_or(|x| x > 1));

Option 提取包含的值

expect(msg) -> T - 返回 Some 中的值,None 时 panic 并附带消息

1
2
3
4
let x = Some("value");
assert_eq!(x.expect("should have value"), "value");

// None.expect("msg") 会 panic: msg

unwrap() -> T - 返回 Some 中的值,None 时 panic

1
2
3
4
let x = Some("air");
assert_eq!(x.unwrap(), "air");

// None.unwrap() 会 panic

unwrap_or(default) -> T - 返回 Some 中的值,None 时返回默认值(参数立即求值)

1
2
assert_eq!(Some("car").unwrap_or("bike"), "car");
assert_eq!(None.unwrap_or("bike"), "bike");

unwrap_or_else(f) -> T - 返回 Some 中的值,None 时调用闭包计算默认值(延迟求值)

1
2
3
let k = 10;
assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4);
assert_eq!(None.unwrap_or_else(|| 2 * k), 20);

unwrap_or_default() -> T - 返回 Some 中的值,None 时返回类型的 Default

1
2
3
4
let x: Option<u32> = None;
let y: Option<u32> = Some(12);
assert_eq!(x.unwrap_or_default(), 0);
assert_eq!(y.unwrap_or_default(), 12);

unwrap_unchecked() - unsafe,不检查直接返回值,None 时是未定义行为

1
2
let x = Some("air");
assert_eq!(unsafe { x.unwrap_unchecked() }, "air");

Option 转换包含的值

map(f) -> Option<U> - 对 Some 中的值应用函数,None 保持不变

1
2
3
4
5
6
let maybe_some_string = Some(String::from("Hello, World!"));
let maybe_some_len = maybe_some_string.map(|s| s.len());
assert_eq!(maybe_some_len, Some(13));

let x: Option<&str> = None;
assert_eq!(x.map(|s| s.len()), None);

inspect(f) -> Option<T> - 如果是 Some,则调用 f,传入 Some 中值的引用,返回原 Option(1.76+)

1
2
let list = vec![1, 2, 3];
list.get(1).inspect(|x| println!("got: {x}"));

map_or(default, f) -> U - Some 时应用函数返回函数的结果,None 时返回默认值(参数立即求值)

1
2
3
4
5
let x = Some("foo");
assert_eq!(x.map_or(42, |v| v.len()), 3);

let x: Option<&str> = None;
assert_eq!(x.map_or(42, |v| v.len()), 42);

map_or_else(default_fn, f) -> U - Some 时应用函数返回函数结果,None 时调用 default_fn 计算默认值并返回

1
2
3
4
5
6
let k = 21;
let x = Some("foo");
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3);

let x: Option<&str> = None;
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);

and(optb) -> Option<U> - Some 时返回 optbNone 时返回 None(参数立即求值)

1
2
3
4
5
6
7
let x = Some(2);
let y: Option<&str> = None;
assert_eq!(x.and(y), None);

let x = Some(2);
let y = Some("foo");
assert_eq!(x.and(y), Some("foo"));

and_then(f) -> Option<U> - Some 时调用函数返回新 Option,None 时返回 None

1
2
3
4
5
fn sq(x: u32) -> Option<u32> { x.checked_mul(x) }

assert_eq!(Some(2).and_then(sq), Some(4));
assert_eq!(Some(1_000_000).and_then(sq), None);
assert_eq!(None.and_then(sq), None);

or(optb) -> Option<T> - Some 时返回自身,None 时返回 optb(参数立即求值)

1
2
3
4
5
6
7
let x = Some(2);
let y = None;
assert_eq!(x.or(y), Some(2));

let x = None;
let y = Some(100);
assert_eq!(x.or(y), Some(100));

or_else(f) -> Option<T> - Some 时返回自身,None 时调用函数返回新 Option

1
2
3
4
5
6
fn nobody() -> Option<&'static str> { None }
fn vikings() -> Option<&'static str> { Some("vikings") }

assert_eq!(Some("barbarians").or_else(vikings), Some("barbarians"));
assert_eq!(None.or_else(vikings), Some("vikings"));
assert_eq!(None.or_else(nobody), None);

xor(optb) -> Option<T> - 当 optb 和自身恰好一个为 Some 时返回该值,否则返回 None

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let x = Some(2);
let y: Option<u32> = None;
assert_eq!(x.xor(y), Some(2));

let x: Option<u32> = None;
let y = Some(2);
assert_eq!(x.xor(y), Some(2));

let x = Some(2);
let y = Some(2);
assert_eq!(x.xor(y), None);

let x: Option<u32> = None;
let y: Option<u32> = None;
assert_eq!(x.xor(y), None);

filter(predicate) -> Option<T> - 当 selfNone 时,返回 None ,否则当 predicate 返回 true 时返回自身,否则返回 None

1
2
3
4
5
fn is_even(n: &i32) -> bool { n % 2 == 0 }

assert_eq!(None.filter(is_even), None);
assert_eq!(Some(3).filter(is_even), None);
assert_eq!(Some(4).filter(is_even), Some(4));

Option 与 Result 互转方法

ok_or(err) -> Result<T, E> - Some(v)Ok(v)NoneErr(err)(参数立即求值)

1
2
3
4
5
let x = Some("foo");
assert_eq!(x.ok_or(0), Ok("foo"));

let x: Option<&str> = None;
assert_eq!(x.ok_or(0), Err(0));

ok_or_else(f) -> Result<T, E> - Some(v)Ok(v)NoneErr(f())(延迟求值)

1
2
3
4
5
let x = Some("foo");
assert_eq!(x.ok_or_else(|| 0), Ok("foo"));

let x: Option<&str> = None;
assert_eq!(x.ok_or_else(|| 0), Err(0));

Option 处理引用的适配器

as_ref() -> Option<&T> - &Option<T>Option<&T>

1
2
3
4
let text: Option<String> = Some("Hello, world!".to_string());
let text_length: Option<usize> = text.as_ref().map(|s| s.len());
// text 仍可继续使用
println!("{text:?}");

as_mut() -> Option<&mut T> - &mut Option<T>Option<&mut T>

1
2
3
4
5
6
let mut x = Some(2);
match x.as_mut() {
Some(v) => *v = 42,
None => {},
}
assert_eq!(x, Some(42));

as_deref() -> Option<&T::Target> - Option<T>Option<&T::Target>,T 需实现 Deref

1
2
3
4
5
let x: Option<String> = Some("hey".to_owned());
assert_eq!(x.as_deref(), Some("hey"));

let x: Option<String> = None;
assert_eq!(x.as_deref(), None);

as_deref_mut() -> Option<&mut <T as DerefMut>::Target> - Option<T> / &mut Option<T>Option<&mut T::Target>,T 需实现 DerefMut

1
2
let mut x: Option<String> = Some("hey".to_owned());
assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), Some("HEY"));

cloned() -> Option<T> - Option<&T>Option<T>,T 需实现 Clone

1
2
3
let x = 12;
let cloned: Option<i32> = Some(&x).cloned();
assert_eq!(cloned, Some(12));

copied() -> Option<T> - Option<&T>Option<T>,T 需实现 Copy

1
2
3
let x = 12;
let copied: Option<i32> = Some(&x).copied();
assert_eq!(copied, Some(12));

Option 原地操作

insert(value) -> &mut T - 插入值并返回可变引用,已有值会被 drop

1
2
3
4
5
6
7
8
9
let mut opt = None;
let val = opt.insert(42);
assert_eq!(*val, 42);
assert_eq!(opt, Some(42));

// 覆盖已有值
let val = opt.insert(0);
assert_eq!(*val, 0);
assert_eq!(opt, Some(0));

get_or_insert(value) -> &mut T - 如果为 None 则插入值,返回可变引用

1
2
3
4
5
6
let mut x = None;
let y = x.get_or_insert(5);
assert_eq!(y, &5);

*y = 10;
assert_eq!(x, Some(10));

get_or_insert_with(f) -> &mut T - 如果为 None 则调用闭包插入值,返回一个可变引用

1
2
3
let mut x = None;
let y = x.get_or_insert_with(|| 5);
assert_eq!(y, &5);

get_or_insert_default() -> &mut T - 如果为 None 则插入 Default::default()(1.83+)

1
2
3
4
let mut x: Option<Vec<u32>> = None;
let y = x.get_or_insert_default();
y.push(42);
assert_eq!(x, Some(vec![42]));

take() -> Option<T> - 取出值,将 Option 置为 None

1
2
3
4
let mut x = Some(2);
let y = x.take();
assert_eq!(y, Some(2));
assert_eq!(x, None);

take_if(predicate) -> Option<T> - 当 predicate 返回 true 时取出值,否则返回 None

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let mut x = Some(42);

let prev = x.take_if(|v| if *v == 42 {
*v += 1;
false
} else {
false
});
assert_eq!(x, Some(43));
assert_eq!(prev, None);

let prev = x.take_if(|v| *v == 43);
assert_eq!(x, None);
assert_eq!(prev, Some(43));

replace(value) -> Option<T> - 替换值,返回旧值

1
2
3
4
5
6
7
8
9
let mut x = Some(2);
let old = x.replace(5);
assert_eq!(x, Some(5));
assert_eq!(old, Some(2));

let mut x = None;
let old = x.replace(3);
assert_eq!(x, Some(3));
assert_eq!(old, None);

Option 组合操作

zip(other) -> Option<(T, U)> - 组合两个 Option,任一为 None 则返回 None

1
2
3
4
5
6
let x = Some(1);
let y = Some("hi");
let z = None::<u8>;

assert_eq!(x.zip(y), Some((1, "hi")));
assert_eq!(x.zip(z), None);

zip_with(other, f) -> Option<R> - 组合两个 Option 并用函数处理,nightly 特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#![feature(option_zip)]

#[derive(Debug, PartialEq)]
struct Point {
x: f64,
y: f64,
}

impl Point {
fn new(x: f64, y: f64) -> Self {Self { x, y }}
}

let x = Some(17.5);
let y = Some(42.7);

assert_eq!(x.zip_with(y, Point::new), Some(Point { x: 17.5, y: 42.7 }));
assert_eq!(x.zip_with(None, Point::new), None);

unzip() - Option<(A, B)>(Option<A>, Option<B>)

1
2
3
4
let x = Some((1, "hi"));
let y = None::<(u8, u32)>;
assert_eq!(x.unzip(), (Some(1), Some("hi")));
assert_eq!(y.unzip(), (None, None));

Option 嵌套展开

flatten() -> Option<T> - Option<Option<T>>Option<T>,(flatten 只移除一层嵌套)

1
2
3
4
5
6
7
8
let x: Option<Option<u32>> = Some(Some(6));
assert_eq!(x.flatten(), Some(6));

let x: Option<Option<u32>> = Some(None);
assert_eq!(x.flatten(), None);

let x: Option<Option<u32>> = None;
assert_eq!(x.flatten(), None);

transpose() -> Result<Option<T>, E> - Option<Result<T, E>>Result<Option<T>, E>

1
2
3
let x: Option<Result<i32, SomeErr>> = Some(Ok(5));
let y: Result<Option<i32>, SomeErr> = Ok(Some(5));
assert_eq!(x.transpose(), y);

Option 迭代器

iter() - 返回包含 0 或 1 个元素的迭代器

1
2
3
4
5
let x = Some(4);
assert_eq!(x.iter().next(), Some(&4));

let x: Option<u32> = None;
assert_eq!(x.iter().next(), None);

iter_mut() - 返回可变迭代器

1
2
3
4
5
6
let mut x = Some(4);
match x.iter_mut().next() {
Some(v) => *v = 42,
None => {},
}
assert_eq!(x, Some(42));

切片转换

as_slice() - Some 返回单元素切片,None 返回空切片(1.75+)

1
2
assert_eq!(Some(1234).as_slice(), &[1234]);
assert_eq!(None::<u32>.as_slice(), &[]);

as_mut_slice() - Some 返回可变切片,None 返回空切片(1.75+)

1
2
3
let mut x = Some(1234);
x.as_mut_slice()[0] += 1;
assert_eq!(x, Some(1235));

Result

Result 官方文档地址: enum.Result

Result 的定义如下:

1
2
3
4
pub enum Result<T, E> {
Ok(T),
Err(E),
}

Result 方法速查

分类 方法 说明
判断 is_ok() / is_err() 判断是 Ok / Err
判断 is_ok_and(f) / is_err_and(f) Ok 且满足条件 / Err 且满足条件
提取 unwrap() / expect(msg) 提取成功值,失败时 panic
提取 unwrap_or(v) / unwrap_or_else(f) 提取成功值或提供默认值
提取 unwrap_or_default() 提取成功值或使用 Default
提取 unwrap_err() / expect_err(msg) 提取错误值,成功时 panic
转换 map(f) / map_err(f) 转换 Ok 值 / Err
转换 map_or(v, f) / map_or_else(f, g) 转换或提供默认值
转换 inspect(f) / inspect_err(f) 执行副作用
链式 and(res) / and_then(f) Ok 时继续链式调用
链式 or(res) / or_else(f) Err 时回退备选值
引用 as_ref() / as_mut() 转为引用的 Result
引用 as_deref() / as_deref_mut() 解引用引用
引用 cloned() / copied() Result<&T, E>Result<T, E>
展开 flatten() / transpose() 嵌套展开
迭代 iter() / iter_mut() 转为迭代器
互转 ok() / err() Option

Result 查询变体(条件判断)

is_ok() -> bool - 判断是否为 Ok

1
2
3
4
5
let x: Result<i32, &str> = Ok(-3);
assert!(x.is_ok());

let x: Result<i32, &str> = Err("error");
assert!(!x.is_ok());

is_ok_and(f) -> bool - 为 Ok 且 f 函数返回 true 则返回 true(1.70+)

1
2
3
4
5
6
7
8
9
10
11
12
let x: Result<u32, &str> = Ok(2);
assert_eq!(x.is_ok_and(|x| x > 1), true);

let x: Result<u32, &str> = Ok(0);
assert_eq!(x.is_ok_and(|x| x > 1), false);

let x: Result<u32, &str> = Err("hey");
assert_eq!(x.is_ok_and(|x| x > 1), false);

let x: Result<String, &str> = Ok("ownership".to_string());
assert_eq!(x.as_ref().is_ok_and(|x| x.len() > 1), true);
println!("still alive {:?}", x);

is_err() -> bool - 判断是否为 Err

1
2
3
4
5
let x: Result<i32, &str> = Ok(-3);
assert!(!x.is_err());

let x: Result<i32, &str> = Err("error");
assert!(x.is_err());

is_err_and(f) -> bool - 为 Err 且 f 函数返回 true 则返回 true(1.70+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use std::io::{Error, ErrorKind};

let x: Result<u32, Error> = Err(Error::new(ErrorKind::NotFound, "!"));
assert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), true);

let x: Result<u32, Error> = Err(Error::new(ErrorKind::PermissionDenied, "!"));
assert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false);

let x: Result<u32, Error> = Ok(123);
assert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false);

let x: Result<u32, String> = Err("ownership".to_string());
assert_eq!(x.as_ref().is_err_and(|x| x.len() > 1), true);
println!("still alive {:?}", x);

Result 提取包含的值

expect(msg) -> T - 返回 Ok 中的值,Err 时 panic 并附带消息

1
2
3
4
let x: Result<u32, &str> = Ok(2);
assert_eq!(x.expect("should be ok"), 2);

// Err("e").expect("msg") 会 panic: msg: e

unwrap() -> T - 返回 Ok 中的值,Err 时 panic

1
2
3
4
let x: Result<u32, &str> = Ok(2);
assert_eq!(x.unwrap(), 2);

// Err("e").unwrap() 会 panic: e

unwrap_or(default) -> T - 返回 Ok 中的值,Err 时返回 default

1
2
3
4
5
let x: Result<u32, &str> = Ok(2);
assert_eq!(x.unwrap_or(0), 2);

let x: Result<u32, &str> = Err("error");
assert_eq!(x.unwrap_or(0), 0);

unwrap_or_else(f) -> T - Err 时返回调用闭包 f 返回的值

1
2
3
4
fn count(x: &str) -> usize { x.len() }

assert_eq!(Ok(2).unwrap_or_else(count), 2);
assert_eq!(Err("foo").unwrap_or_else(count), 3);

unwrap_or_default() -> T - Err 时返回类型的 Default 值

1
2
3
4
5
6
7
let good_year_from_input = "1909";
let bad_year_from_input = "190blarg";
let good_year = good_year_from_input.parse().unwrap_or_default();
let bad_year = bad_year_from_input.parse().unwrap_or_default();

assert_eq!(1909, good_year);
assert_eq!(0, bad_year);

expect_err(msg) -> E - 返回 Err 中的值,Ok 时 panic 并附带消息

1
2
3
4
let x: Result<u32, &str> = Err("error");
assert_eq!(x.expect_err("should be err"), "error");

// Ok(10).expect_err("Testing expect_err"); // panics with `Testing expect_err: 10`

unwrap_err() -> E - 返回 Err 中的值,Ok 时 panic

1
2
3
4
let x: Result<u32, &str> = Err("error");
assert_eq!(x.unwrap_err(), "error");

// Ok(2).unwrap_err(); // panics with `2`

Result 转换包含的值

map(f) -> Result<U, E> - 对 Ok 中的值应用函数,Err 保持不变

1
2
3
4
5
6
let line = "12";
let doubled = line.parse::<i32>().map(|i| i * 2);
assert_eq!(doubled, Ok(24));

let x: Result<u32, &str> = Err("error");
assert_eq!(x.map(|x| x * 2), Err("error"));

map_or(default, f) -> U - Ok 时应用函数,Err 时返回默认值

1
2
3
4
5
let x: Result<_, &str> = Ok("foo");
assert_eq!(x.map_or(42, |v| v.len()), 3);

let x: Result<&str, _> = Err("bar");
assert_eq!(x.map_or(42, |v| v.len()), 42);

map_or_else(default_fn, f) -> U - Ok 时应用函数 fErr 时调用闭包 default_fn

1
2
3
4
5
6
let k = 21;
let x: Result<_, &str> = Ok("foo");
assert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 3);

let x: Result<&str, _> = Err("bar");
assert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 42);

map_err(f) -> Result<T, F> - 对 Err 中的值应用函数,Ok 保持不变

1
2
3
4
5
6
7
fn stringify(x: u32) -> String { format!("error code: {x}") }

let x: Result<u32, u32> = Ok(2);
assert_eq!(x.map_err(stringify), Ok(2));

let x: Result<u32, u32> = Err(13);
assert_eq!(x.map_err(stringify), Err("error code: 13".to_string()));

inspect(f) -> Result<T, E> - 对 Ok 中的值执行函数 f,返回原 Result(1.76+)

1
2
3
4
5
let x: u8 = "4"
.parse::<u8>()
.inspect(|x| println!("original: {x}"))
.map(|x| x.pow(3))
.expect("failed to parse");

inspect_err(f) -> Result<T, E> - 对 Err 中的值执行副作用,返回原 Result(1.76+)

1
2
3
4
5
6
use std::{fs, io};

fn read() -> io::Result<String> {
fs::read_to_string("address.txt")
.inspect_err(|e| eprintln!("failed to read file: {e}"))
}

and(res) -> Result<U, E> - Ok 时返回 resErr 时返回自身错误

1
2
3
4
5
6
7
let x: Result<u32, &str> = Ok(2);
let y: Result<&str, &str> = Err("late error");
assert_eq!(x.and(y), Err("late error"));

let x: Result<u32, &str> = Err("early error");
let y: Result<&str, &str> = Ok("foo");
assert_eq!(x.and(y), Err("early error"));

and_then(f) -> Result<U, E> - Ok 时调用函数返回新 Result,Err 时返回自身

1
2
3
4
fn sq(x: u32) -> Result<u32, u32> { x.checked_mul(x).ok_or(x) }

assert_eq!(Ok(2).and_then(sq), Ok(4));
assert_eq!(Err(3).and_then(sq), Err(3));

or(res) -> Result<T, F> - Err 时返回 resOk 时返回自身

1
2
3
4
5
6
7
let x: Result<u32, &str> = Ok(2);
let y: Result<u32, &str> = Err("late error");
assert_eq!(x.or(y), Ok(2));

let x: Result<u32, &str> = Err("early error");
let y: Result<u32, &str> = Ok(2);
assert_eq!(x.or(y), Ok(2));

or_else(f) -> Result<T, F> - Err 时调用函数返回新 Result,Ok 时返回自身

1
2
3
4
5
fn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }
fn err(x: u32) -> Result<u32, u32> { Err(x) }

assert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2));
assert_eq!(Err(3).or_else(sq).or_else(err), Ok(9));

Result 与 Option 互转方法

ok() -> Option<T> - Result<T, E>Option<T>,丢弃错误信息

1
2
3
4
5
let x: Result<u32, &str> = Ok(2);
assert_eq!(x.ok(), Some(2));

let x: Result<u32, &str> = Err("Nothing here");
assert_eq!(x.ok(), None);

err() -> Option<E> - Result<T, E>Option<E>,丢弃成功值

1
2
3
4
5
let x: Result<u32, &str> = Ok(2);
assert_eq!(x.err(), None);

let x: Result<u32, &str> = Err("Nothing here");
assert_eq!(x.err(), Some("Nothing here"));

Result 处理引用的适配器

as_ref() -> Result<&T, &E> - &Result<T, E>Result<&T, &E>

1
2
3
4
5
let x: Result<u32, &str> = Ok(2);
assert_eq!(x.as_ref(), Ok(&2));

let x: Result<u32, &str> = Err("Error");
assert_eq!(x.as_ref(), Err(&"Error"));

as_mut() -> Result<&mut T, &mut E> - &mut Result<T, E>Result<&mut T, &mut E>

1
2
3
4
5
6
let mut x: Result<i32, i32> = Ok(2);
match x.as_mut() {
Ok(v) => *v = 42,
Err(e) => *e = 0,
}
assert_eq!(x, Ok(42));

as_deref() -> Result<&T::Target, &E> - Result<T, E>Result<&T::Target, &E>

1
2
let x: Result<String, u32> = Ok("hello".to_string());
assert_eq!(x.as_deref(), Ok("hello"));

as_deref_mut() -> Result<&mut T::Target, &mut E> - Result<T, E>Result<&mut T::Target, &mut E>

1
2
let mut x: Result<String, u32> = Ok("hey".to_string());
x.as_deref_mut().map(|x| x.make_ascii_uppercase());

cloned() -> Result<T, E> - Result<&T, E>Result<T, E>

1
2
3
let x = 12;
let cloned: Result<i32, &str> = Ok(&x).cloned();
assert_eq!(cloned, Ok(12));

copied() - Result<&T, E>Result<T, E>

1
2
3
let x = 12;
let copied: Result<i32, &str> = Ok(&x).copied();
assert_eq!(copied, Ok(12));

Result 嵌套展开

flatten() -> Result<T, E> - Result<Result<T, E>, E>Result<T, E>,展开只会移除最外层嵌套

1
2
3
4
5
6
7
8
let x: Result<Result<i32, &str>, &str> = Ok(Ok(2));
assert_eq!(x.flatten(), Ok(2));

let x: Result<Result<i32, &str>, &str> = Ok(Err("error"));
assert_eq!(x.flatten(), Err("error"));

let x: Result<Result<i32, &str>, &str> = Err("error");
assert_eq!(x.flatten(), Err("error"));

transpose() -> Option<Result<T, E>> - Result<Option<T>, E>Option<Result<T, E>>

1
2
3
4
5
6
7
8
let x: Result<Option<i32>, &str> = Some(Ok(5)).transpose();
assert_eq!(x, Ok(Some(5)));

let x: Result<Option<i32>, &str> = Ok(None);
assert_eq!(x.transpose(), None);

let x: Result<Option<i32>, &str> = Err("error");
assert_eq!(x.transpose(), Some(Err("error")));

Result 迭代器

iter() - 返回包含 0 或 1 个元素的迭代器

1
2
3
4
5
let x: Result<u32, &str> = Ok(7);
assert_eq!(x.iter().next(), Some(&7));

let x: Result<u32, &str> = Err("nothing!");
assert_eq!(x.iter().next(), None);

iter_mut() - 返回可变迭代器

1
2
3
4
5
6
let mut x: Result<u32, &str> = Ok(7);
match x.iter_mut().next() {
Some(v) => *v = 40,
None => {},
}
assert_eq!(x, Ok(40));

Result 和 Option 的 ? 操作符

? 操作符用于在返回 ResultOption 的函数中快速传播错误:

1
2
3
4
5
6
7
8
9
use std::fs::File;
use std::io::Read;

fn read_file() -> Result<String, std::io::Error> {
let mut file = File::open("hello.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}

等价于:

1
2
3
4
5
6
7
8
9
10
11
12
fn read_file() -> Result<String, std::io::Error> {
let mut file = match File::open("hello.txt") {
Ok(f) => f,
Err(e) => return Err(e),
};
let mut contents = String::new();
match file.read_to_string(&mut contents) {
Ok(_) => {},
Err(e) => return Err(e),
}
Ok(contents)
}

? 也可用于 Option

1
2
3
4
fn first_even(numbers: &[i32]) -> Option<i32> {
let first = numbers.first()?;
if first % 2 == 0 { Some(*first) } else { None }
}

Result 和 Option 的常用模式

Result 和 Option 的链式调用

1
2
3
4
5
6
7
8
9
10
// Option 链式
let result = config
.get("database")
.and_then(|db| db.get("host"))
.unwrap_or("localhost");

// Result 链式
let content = std::fs::read_to_string("config.json")
.map_err(|e| format!("读取失败: {e}"))
.and_then(|s| serde_json::from_str(&s).map_err(|e| format!("解析失败: {e}")));

Result 和 Option 的错误转换

1
2
3
4
// 使用 map_err 转换错误类型
fn parse_number(s: &str) -> Result<i32, MyError> {
s.parse::<i32>().map_err(|e| MyError::ParseError(e.to_string()))
}

组合多个 Result

1
2
3
4
5
6
7
8
9
10
11
// 全部成功才返回 Ok
let result: Result<Vec<i32>, &str> = vec![Ok(1), Ok(2), Ok(3)]
.into_iter()
.collect();
assert_eq!(result, Ok(vec![1, 2, 3]));

// 遇到第一个 Err 就返回
let result: Result<Vec<i32>, &str> = vec![Ok(1), Err("error"), Ok(3)]
.into_iter()
.collect();
assert_eq!(result, Err("error"));