iT邦幫忙

2023 iThome 鐵人賽

DAY 11
0

昨天我們提到了 Rust 的 Error Handling

今天我們要再來介紹 unwrap 以及 expect

昨天我們用 Result 以及 Option 時,會搭配 match 來簡化程式碼

不過還有其他兩種錯誤處理方式,是 unwrap 以及 expect

為什麼還需要 unwrap 以及 expect?

  • 想快速知道程式碼的結果是否成立或存在
  • 會啟用 panic!,不過會導致整個程式碼停止編譯或執行

unwrap

當我們想確認這個東西是否存在時,可以用 unwrap 來確認,
不存在會引發 panic! ,我們就可以透過這個 panic! 來確認哪裡有問題

不過相較於 match 來說,
match 可以針對不同的錯誤狀況定義不同的錯誤訊息,
unwrap 就只是提供一個粗略的錯誤訊息而已

fn main() {
    let d = demo("Ning").unwrap();

    println!("{}", d)
}

fn demo(user: &str) -> Option<&str> {
    if user.is_empty() {
        return None;
    } else {
        return Some(user);
    }
}
> Cargo run 

Ning

讓我們來看噴 panic! 的例子

fn main() {
    let d = demo("").unwrap();

    println!("{}", d)
}

fn demo(user: &str) -> Option<&str> {
    if user.is_empty() {
        return None;
    } else {
        return Some(user);
    }
}

還記得我們會用 Option<T> 來檢查這東西是不是存在嗎?
不存在的話,unwrap 就會噴一個 panic!

> cargo run

thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:2:22
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

expect

unwrap 蠻類似的,有誤的時候會引發 panic!,跟 unwrap 差別在於 expect 可以加上自定義的錯誤訊息

另外 Result 也可以使用 expect

fn main() {
    let d = demo("Ning").expect("without user");

    println!("{}", d)
}

fn demo(user: &str) -> Option<&str> {
    if user.is_empty() {
        return None;
    } else {
        return Some(user);
    }
}
> Cargo run 

Ning

當這個東西不存在時,我們想額外定義 panic! 的錯誤訊息,
這時候可以當作 expect 的參數

fn main() {
    let d = demo("").expect("without user");

    println!("{}", d)
}

fn demo(user: &str) -> Option<&str> {
    if user.is_empty() {
        return None;
    } else {
        return Some(user);
    }
}

> cargo run

thread 'main' panicked at 'without user', src/main.rs:2:22
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

跟 match 的差別是什麼?

https://ithelp.ithome.com.tw/upload/images/20230926/20150947iTesraGROx.jpg

更簡潔的判斷 ?

我們還可以用更簡潔的方式來判斷 Result 與 Option 是否有誤

use std::num::ParseIntError;

fn main() {
    let result = parsing();

    println!("{:?}", result)
}

fn parsing() -> Result<i32, ParseIntError> {
    let x: i32 = "12".parse()?;
    Ok(x)
}
> cargo run

Ok(12)

如果是錯誤的話呢?

use std::num::ParseIntError;

fn main() {
    let result = parsing();

    println!("{:?}", result)
}

fn parsing() -> Result<i32, ParseIntError> {
    let x: i32 = "aa".parse()?;
    Ok(x)
}

就會直接走 Result<T, E> 中的 E 這條

> cargo run

Err(ParseIntError { kind: InvalidDigit })

用起來其實蠻方便又簡潔


上一篇
Day 10 Error Handling
下一篇
Day 12 Macro
系列文
成為程式界的 F1 賽車手,用 30 天認識 Rust 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言