前言
在 Rust 中,有两个非常常用的枚举类型:Option 和 Result。它们替代了其他语言中的 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");
|
unwrap() -> T - 返回 Some 中的值,None 时 panic
1 2 3 4
| let x = Some("air"); assert_eq!(x.unwrap(), "air");
|
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 时返回 optb,None 时返回 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> - 当 self 为 None 时,返回 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),None 转 Err(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),None 转 Err(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());
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);
|
unwrap() -> T - 返回 Ok 中的值,Err 时 panic
1 2 3 4
| let x: Result<u32, &str> = Ok(2); assert_eq!(x.unwrap(), 2);
|
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");
|
unwrap_err() -> E - 返回 Err 中的值,Ok 时 panic
1 2 3 4
| let x: Result<u32, &str> = Err("error"); assert_eq!(x.unwrap_err(), "error");
|
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 时应用函数 f ,Err 时调用闭包 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 时返回 res,Err 时返回自身错误
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 时返回 res,Ok 时返回自身
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 的 ? 操作符
? 操作符用于在返回 Result 或 Option 的函数中快速传播错误:
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
| let result = config .get("database") .and_then(|db| db.get("host")) .unwrap_or("localhost");
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
| 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
| let result: Result<Vec<i32>, &str> = vec![Ok(1), Ok(2), Ok(3)] .into_iter() .collect(); assert_eq!(result, Ok(vec![1, 2, 3]));
let result: Result<Vec<i32>, &str> = vec![Ok(1), Err("error"), Ok(3)] .into_iter() .collect(); assert_eq!(result, Err("error"));
|