要不是使用「?」,Rust的錯誤處理會顯得有些不夠靈巧。要使用「?」咱們須要聲明返回值類型爲Result類型,這種類型能夠包含任何具有std::error::Error
特徵從而能夠轉換爲Bax<Error>
類型的錯誤類型。
拿咱們須要處理IO錯誤和字符串轉換爲數字錯誤舉例:html
use std::fs::File; use std::io::prelude::*; use std::error::Error; fn run(file: &str) -> Result<i32, Box<Error>> { let mut file = File::open(file)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents.trim().parse()?) }12345678910
這裏使用了倆個"?"處理可能發生的IO錯誤:打開文件錯誤和讀取內容爲string錯誤。
使用了一個「?」處理可能發生的類型轉換錯誤。
最後咱們將結果包裝爲Ok
類型。Rust能夠中返回值中判斷出parse
的結果爲i32
類型。
簡化Result
類型的聲明比較容易,咱們能夠定義一個本身的Result類型,好比:git
type BoxResult<T> = Result<T, Box<Error>>1
可是,咱們程序還須要自定義Error
類型,那咱們就須要作些其餘工做:github
Debug
特徵Display
特徵Error
特徵就像這樣:app
//error1.rs use std::error::Error; use std::fmt; #[derive(Debug)] struct MyError { details: String } impl MyError { fn new(msg: &str) -> MyError { MyError{details: msg.to_string()} } } impl fnt::Display for MyError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Reuslt { write!(f, "{}", self.details) } } impls Error for MyError { fn description(&self) -> &str { &self.details } } //一個測試咱們自定義錯誤的函數 fn raises_my_error(yes: bool) -> Result<(), MyError> { if yes { Err(MyError::new("borked")) } else { Ok(()) } }1234567891011121314151617181920212223242526272829303132333435
輸入Result<T, MyError>
比較麻煩,因此不少模塊都定義了本身的Result類型,這樣能夠少敲幾下鍵盤。好比IO模塊定義了io::Reust<T>
代替Result<T, io::Error>
使用。
在下面的例子中演示的是怎麼處理String類型轉化爲浮點數類型可能出現錯誤的狀況。
如今咱們知道使用"?"能夠方便的把有錯誤的表達式轉換爲Err返回。這種轉換是經過From
特徵實現的。
你能夠繼續使用這種方便的轉換,這在一些比較簡單的應用中是個不錯的選擇,接下來咱們演示的場景會複雜一些。ParseFloatError
實現了Error
特徵,因此它具有description()
方法。ide
use std::num::ParseFloatError; impl From<ParseFloatError> for MyError { fn from(err: ParseFloatError) -> Self { MyError::new(err.description()) } } fn parse_f64(s: &str, yes: bool) -> Result<f64, MyError> { raise_my_error(yes)?; let x: f64 = s.parse()? Ok(x) } fn main() { println!(" {:?}", parse_f64("42", false)); println!(" {:?}", parse_f64("42", true)); println!(" {:?}", parse_64("?42", false)); }123456789101112131415161718
執行結果會是這樣:函數
Ok(42)
Err(MyError {details: 「borked」})
Err(MyError {details: 「invalid float literal」})測試
原文地址spa