You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Result 的 E 类型参数不一定是实现了 Error 的类型,其是一个 std::error::Error
但 E 这是一个 trait
任何实现 Error 的类型都必须同时实现这两个特性:
Display trait,能{}和 format! 一起使用
Debug trait,能使用 format! 和{:?}一起使用
例子
#[derive(Debug)]pubstructMyError(String);impl std::fmt::DisplayforMyError{fnfmt(&self,f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result{write!(f,"{}",self.0)}}impl std::error::ErrorforMyError{}pubfnfind_user(username:&str) -> Result<UserId,MyError>{let f = std::fs::File::open("/etc/passwd").map_err(|e| {MyError(format!("Failed to open password file: {:?}", e))})?;// ...}
实现 From trait 会让字符串值很容易转换成 MyError 实例
遇到问号操作符(?)时,编译器会自动应用任何相关的 From trait 实现,以达到错误返回类型的目的。
就能进一步减少书写
pubfnfind_user(username:&str) -> Result<UserId,MyError>{let f = std::fs::File::open("/etc/passwd").map_err(|e| format!("Failed to open password file: {:?}", e))?;// ...}
/// Return the first line of the given file.pubfnfirst_line(filename:&str) -> Result<String,MyError>{let file = std::fs::File::open(filename)?;// via `From<std::io::Error>`letmut reader = std::io::BufReader::new(file);letmut buf = vec![];let len = reader.read_until(b'\n',&mut buf)?;// via `From<std::io::Error>`let result = String::from_utf8(buf)?;// via `From<std::string::FromUtf8Error>`if result.len() > MAX_LEN{returnErr(MyError::General(format!("Line too long: {}", len)));}Ok(result)}
fnmain(){// some code// if we need to debug in herepanic!();// or panic!("xxx is xx ")}// -------------- Compile time error --------------
thread 'main' panicked at 'explicit panic', src/main.rs:5:5
use std::collections::HashMap;fnmain(){matchget_current_date(){Ok(date) => println!("We've time travelled to {}!!", date),Err(e) => eprintln!("Oh noes, we don't know which era we're in! :( \n {}", e),}}fnget_current_date() -> Result<String, reqwest::Error>{let url = "https://postman-echo.com/time/object";let res = reqwest::blocking::get(url)?.json::<HashMap<String,i32>>()?;let date = res["years"].to_string();Ok(date)}
? 运算符与 unwrap 类似,但它不会 panic,而是将错误传播给调用函数。
只能对 Result 或者 Option 使用?运算符
透出多个错误
use chrono::NaiveDate;use std::collections::HashMap;fnmain(){matchget_current_date(){Ok(date) => println!("We've time travelled to {}!!", date),Err(e) => eprintln!("Oh noes, we don't know which era we're in! :( \n {}", e),}}
- fn get_current_date() -> Result<String, reqwest::Error> {
+ fnget_current_date() -> Result<String,Box<dyn std::error::Error>>{let url = "https://postman-echo.com/time/object";let res = reqwest::blocking::get(url)?.json::<HashMap<String,i32>>()?;let formatted_date = format!("{}-{}-{}", res["years"], res["months"] + 1, res["date"]);let parsed_date = NaiveDate::parse_from_str(formatted_date.as_str(),"%Y-%m-%d")?;let date = parsed_date.format("%Y %B %d").to_string();Ok(date)}
fndivide(a:i64,b:i64) -> i64{if b == 0{panic!("Cowardly refusing to divide by zero!");}
a / b
}fndivide_recover(a:i64,b:i64,default:i64) -> i64{let result = std::panic::catch_unwind(|| divide(a, b));match result {Ok(x) => x,Err(_) => default,}}let result = divide_recover(0,0,42);println!("result = {}", result);// result = 42
对数据结构进行操作的中途发生了异常,那么就无法保证数据结构处于自洽状态。
在存在 exception 的情况下维护内部不变性是一件极其困难的事情,
panic 传播与 FFI 边界的交互也很差;
对于库代码来说,最好的替代方法是通过返回一个带有适当错误类型的 Result 来使错误成为别人的问题
use thiserror::Error;#[derive(Error,Debug)]pubenumDataStoreError{#[error("data store disconnected")]Disconnect(#[from] io::Error),#[error("the data for key `{0}` is not available")]Redaction(String),#[error("invalid header (expected {expected:?}, found {found:?})")]InvalidHeader{expected:String,found:String,},#[error("unknown data store error")]Unknown,}
参考资料
Error trait
例子
nested errors
panic
unreachable or unimplemented
透出错误
?
运算符与unwrap
类似,但它不会 panic,而是将错误传播给调用函数。透出多个错误
Box<dyn std::error::Error>
非常方便应用程序和库
Box<dyn std::error::Error>
时,具体类型信息将被删除。error handling for iteration
创建自定义错误
Box<Error>
。reqwest::Error
chrono::format::ParseError
。MyCustomError::HttpError
和MyCustomError::PkarseError
Don't panic
宁愿返回 Result 也不愿使用 panic
一些帮助处理错误的 crate
thiserror
anyhow
eyre
#type/rust #public
The text was updated successfully, but these errors were encountered: