Ale*_*nov 5 error-handling rust
因此Result<T, E>有一个非常简洁的方法map_err,允许以功能性的方式处理错误:
use std::io::Result;
use std::error::Error;
use std::string::ToString;
use std::io;
fn init() -> Result<u32> { Ok(42) }
fn do_work(_data: u32) -> Result<()> { Err(io::Error::new(io::ErrorKind::Other, "IO Error!")) }
fn handle_error<E: Error + ToString>(error: E, message: &str) -> E {
eprintln!("{}: {}", message, error.to_string());
error
}
fn main() {
let _ = init()
.map_err(|e| handle_error(e, "Init error"))
.and_then(do_work)
.map_err(|e| handle_error(e, "Work error")); // "Work error: IO error"
}
Run Code Online (Sandbox Code Playgroud)
如果有相同的功能风格来处理,那就太酷了Option<T>::None:
use std::io::Result;
use std::error::Error;
use std::string::ToString;
use std::io;
fn init_opt() -> Option<u32> { Some(42) }
fn do_work_opt(_data: u32) -> Option<()> { None }
fn handle_none(message: &str) {
eprintln!("{}", message);
}
fn main() {
let _ = init_opt()
.map_none(|| handle_none("Init error"))
.and_then(do_work_opt)
.map_none(|| handle_none("Work error")); // "Work error"
}
Run Code Online (Sandbox Code Playgroud)
可以使用这样的自定义特征来完成
trait MapNone {
fn map_none(self, op: impl FnOnce() -> ()) -> Self;
}
impl<T> MapNone for Option<T> {
fn map_none(self, op: impl FnOnce() -> ()) -> Self {
if self.is_none() { op(); }
self
}
}
Run Code Online (Sandbox Code Playgroud)
但我确信我错过了一些东西,并且有一些很好的方法可以通过标准库做同样的事情。
该函数Option::or_else是您所提议的函数的通用形式。它不要求它的函数返回单位类型,而是返回一个Option,因此只需让它返回None来模拟您的用例即可。
fn main() {
let _ = init_opt()
.or_else(|| {handle_none("Init error"); None})
.and_then(do_work_opt)
.or_else(|| {handle_none("Work error"); None}); // "Work error"
}
Run Code Online (Sandbox Code Playgroud)
当然,现在也可以返回Some(x)而不是以不同的方式分支。
最后,or_elseandand_then还可以与 结合使用map_or_else:
fn main() {
let _ = init_opt()
.map_or_else(|| {handle_none("Init error"); None}, do_work_opt)
.or_else(|| {handle_none("Work error"); None}); // "Work error"
}
Run Code Online (Sandbox Code Playgroud)
此代码应执行与上面相同的操作;map_or_else分支取决于选项是否是None或包含值。
| 归档时间: |
|
| 查看次数: |
3874 次 |
| 最近记录: |