<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                > The best-laid plans of mice and men Often go awry > > "Tae a Moose", Robert Burns > > 不管是人是鼠,即使最如意的安排設計,結局也往往會出其不意 > > 《致老鼠》,羅伯特·彭斯 有時,杯具就是發生了。有一個計劃來應對不可避免會發生的問題是很重要的。Rust提供了豐富的處理你軟件中可能(讓我們現實點:將會)出現的錯誤的支持。 主要有兩種類型的錯誤可能出現在你的軟件中:失敗和恐慌。讓我們先看看它們的區別,接著討論下如何處理他們。再接下來,我們討論如何將失敗升級為恐慌。 ## 失敗 vs. 恐慌 Rust使用了兩個術語來區別這兩種形式的錯誤:失敗和恐慌。_失敗_(_failure_)是一個可以通過某種方式恢復的錯誤。_恐慌_(_panic_)是不能夠恢復的錯誤。 “恢復”又是什么意思呢?好吧,大部分情況,一個錯誤的可能性是可以預料的。例如,考慮一下`from_str`函數: ~~~ from_str("5"); ~~~ 這個函數獲取一個字符串參數然后把它轉換為其它類型。不過因為它是一個字符串,你不能夠確定這個轉換是否能成功。例如,這個應該轉壞成什么呢? ~~~ from_str("hello5world"); ~~~ 這不能工作。所以我們知道這個函數只對一些輸入能夠正常工作。這是我們期望的行為。我們叫這類錯誤為_失敗_。 另一方面,有時,會出現意料之外的錯誤,或者我們不能從中恢復。一個典型的例子是`assert!`: ~~~ assert!(x == 5); ~~~ 我們用`assert!`聲明某值為true。如果它不是true,很糟的事情發生了。嚴重到我們不能再當前狀態下繼續執行。另一個例子是使用`unreachable!()`宏: ~~~ enum Event { NewRelease, } fn probability(_: &Event) -> f64 { // real implementation would be more complex, of course 0.95 } fn descriptive_probability(event: Event) -> &'static str { match probability(&event) { 1.00 => "certain", 0.00 => "impossible", 0.00 ... 0.25 => "very unlikely", 0.25 ... 0.50 => "unlikely", 0.50 ... 0.75 => "likely", 0.75 ... 1.00 => "very likely", } } fn main() { std::io::println(descriptive_probability(NewRelease)); } ~~~ 這會給我們一個錯誤: ~~~ error: non-exhaustive patterns: `_` not covered [E0004] ~~~ 雖然我們知道我們覆蓋了所有可能的分支,不過Rust不能確定。它不知道概率是在0.0和1.0之間的。所以我們加上另一個分支: ~~~ use Event::NewRelease; enum Event { NewRelease, } fn probability(_: &Event) -> f64 { // real implementation would be more complex, of course 0.95 } fn descriptive_probability(event: Event) -> &'static str { match probability(&event) { 1.00 => "certain", 0.00 => "impossible", 0.00 ... 0.25 => "very unlikely", 0.25 ... 0.50 => "unlikely", 0.50 ... 0.75 => "likely", 0.75 ... 1.00 => "very likely", _ => unreachable!() } } fn main() { println!("{}", descriptive_probability(NewRelease)); } ~~~ 我們永遠也不應該觸發`_`分支,所以我們使用`unreachable!()`宏來表明它。`unreachable!()`返回一個不同于`Result`的錯誤。Rust叫這類錯誤為恐慌。 ## 使用`Option`和`Result`來處理錯誤 最簡單的表明函數會失敗的方法是使用`Option`類型。還記得我們的`from_str()`例子嗎?這是它的函數標記: ~~~ pub fn from_str<A: FromStr>(s: &str) -> Option<A> ~~~ `from_str()`返回一個`Option`。如果轉換成功了,會返回`Some(value)`,如果失敗了,返回`None`。 這對最簡單的情況是合適的,不過在出錯時并沒有給出足夠的信息。如果我們想知道“為什么”轉換失敗了呢?為此,我們可以使用`Result`類型。它看起來像: ~~~ enum Result<T, E> { Ok(T), Err(E) } ~~~ Rust自身提供了這個枚舉,所以你不需要在你的代碼中定義它。`Ok(T)`變體代表成功,`Err(E)`代表失敗。在所有除了最普通的情況都推薦使用`Result`代替`Option`作為返回值。 這是一個使用`Result`的例子: ~~~ #[derive(Debug)] enum Version { Version1, Version2 } #[derive(Debug)] enum ParseError { InvalidHeaderLength, InvalidVersion } fn parse_version(header: &[u8]) -> Result<Version, ParseError> { if header.len() < 1 { return Err(ParseError::InvalidHeaderLength); } match header[0] { 1 => Ok(Version::Version1), 2 => Ok(Version::Version2), _ => Err(ParseError::InvalidVersion) } } let version = parse_version(&[1, 2, 3, 4]); match version { Ok(v) => { println!("working with version: {:?}", v); } Err(e) => { println!("error parsing header: {:?}", e); } } ~~~ 這個例子使用了個枚舉,`ParseError`,來列舉各種可能出現的錯誤。 ## `panic!`和不可恢復錯誤 當一個錯誤是不可預料的和不可恢復的時候,`panic!`宏會引起一個恐慌。這回使當前線程崩潰,并給出一個錯誤: ~~~ panic!("boom"); ~~~ 給出: ~~~ thread '<main>' panicked at 'boom', hello.rs:2 ~~~ 當你運行它的時候。 因為這種情況相對稀少,保守的使用恐慌。 ## 升級失敗為恐慌 在特定的情況下,即使一個函數可能失敗,我們也想把它當成恐慌。例如,`io::stdin().read_line()`返回一個`IoResult`,一種形式的`Result`(目前只有Result了,坐等文檔更新),當讀取行出現錯誤時。這允許我們處理和盡可能從錯誤中恢復。 如果你不想處理這個錯誤,或者只是想終止程序,我們可以使用`unwrap()`方法: ~~~ io::stdin().read_line().unwrap(); ~~~ 如果`Option`是`None`的話`unwrap()`會`panic!`。這基本上就是說“給我一個值,然后如果出錯了的話,直接崩潰。”這與匹配錯誤并嘗試恢復相比更不穩定,不過它的處理明顯更短小。有時,直接崩潰就行。 這是另一個比`unwrap()`稍微聰明點的做法: ~~~ let input = io::stdin().read_line() .ok() .expect("Failed to read line"); ~~~ `ok()`將`Result`轉換為`Option`,然后`expect()`做了和`unwrap()`同樣的事,不過帶有一個信息。這個信息會傳遞給底層的`panic!`,當錯誤是這樣可以提供更好的錯誤信息。 ## 使用`try!` 當編寫調用那些返回`Result`的函數的代碼時,錯誤處理會是煩人的。`try!`宏在調用棧上隱藏了一些衍生錯誤的樣板。 它可以代替這些: ~~~ use std::fs::File; use std::io; use std::io::prelude::*; struct Info { name: String, age: i32, rating: i32, } fn write_info(info: &Info) -> io::Result<()> { let mut file = File::open("my_best_friends.txt").unwrap(); if let Err(e) = writeln!(&mut file, "name: {}", info.name) { return Err(e) } if let Err(e) = writeln!(&mut file, "age: {}", info.age) { return Err(e) } if let Err(e) = writeln!(&mut file, "rating: {}", info.rating) { return Err(e) } return Ok(()); } ~~~ 為下面這些代碼: ~~~ use std::fs::File; use std::io; use std::io::prelude::*; struct Info { name: String, age: i32, rating: i32, } fn write_info(info: &Info) -> io::Result<()> { let mut file = try!(File::open("my_best_friends.txt")); try!(writeln!(&mut file, "name: {}", info.name)); try!(writeln!(&mut file, "age: {}", info.age)); try!(writeln!(&mut file, "rating: {}", info.rating)); return Ok(()); } ~~~ 在`try!`中封裝一個表達式會返回一個未封裝的正確(`Ok`)值,除非結果是`Err`,在這種情況下`Err`會從當前函數提早返回。 值得注意的是你只能在一個返回`Result`的函數中使用`try!`,這意味著你不能在`main()`中使用`try!`,因為`main()`不返回任何東西。 `try!`使用[From](http://doc.rust-lang.org/nightly/std/convert/trait.From.html)特性來確定錯誤時應該返回什么。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看