中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Result/Option/unwrap/的概念是什么

發布時間:2021-12-29 14:35:58 來源:億速云 閱讀:148 作者:iii 欄目:互聯網科技

本篇內容主要講解“Result/Option/unwrap/的概念是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Result/Option/unwrap/的概念是什么”吧!

1、Option - 可空變量

雖然Rust中有null的概念,但是使用null并不是Rust中常見的模式。假設我們要寫一個函數,輸入一種手機操作系統的名稱,這個函數就會返回其應用商店的名稱。如果傳入字符串iOS,該函數將返回App Store;如果傳入字符串android,那么該函數將返回Play Store。任何其他的輸入都被視為無效。

在大多數開發語言中,我們可以選擇返回null或字符串invalid來表示無效的結果,不過這不是Rust的用法。

地道的Rust代碼應該讓該函數返回一個Option。Option或更確切的說Option<T>是一個泛型,可以是Some<T>None(為了便于閱讀,后續文章中將省略類型參數T)。Rust將SomeNone稱為變體(Variant) —— 這一概念在其他語言中并不存在,因此我也不 去定義到底什么是變體了。

在我們的示例中,正常情況下函數將返回包裹在Some變體中的字符串常量App Store或Play Store。而在非正常情況下,函數將返回None。

fn find_store(mobile_os: &str) -> Option<&str> {
    match mobile_os {
        "iOS" => Some("App Store"),
        "android" => Some("Play Store"),
        _ => None
    }
}

要使用find_store(),我們可以用如下方式調用:

fn main() {
    println!("{}", match find_store("windows") {
        Some(s) => s,
        None => "Not a valid mobile OS"
    });
}

完整的代碼如下:

fn find_store(mobile_os: &str) -> Option<&str> {
    match mobile_os {
        "iOS" => Some("App Store"),
        "android" => Some("Play Store"),
        _ => None
    }
}

fn main() {
    println!("{}", match find_store("windows") {
        Some(s) => s,
        None => "Not a valid mobile OS"
    });
}

2、Result - 包含錯誤信息的結果

Result,或者更確切地說Result<T,E>,是和Rust中的Option相關的概念,它是一個加強版本的Option。

Result<T, E>可能有以下結果之一:

  • Ok(T):結果為成員T

  • Err(E):結果為故障成員E

與之前我們看到Option<T>可以包含Some<T>或None不同,Result中包含了錯誤相關信息,這是Option中所沒有的。

讓我們看一個函數實例,它返回一個Result。該函數摘自用于解析JSON字符串的serde_json庫,其簽名為:

pub fn from_str<'a, T>(s: &'a str) -> Result<T, Error> 
where
    T: Deserialize<'a>,

假設我們要解析如下的字符串:

let json_string = r#"
    {
        "name": "John Doe",
        "age": 43,
        "phones": [
            "+44 1234567",
            "+44 2345678"
        ]
    }"#;

目標是解析為Rust的一個person結構對象:

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    phones: Vec<String>,
}

解析過程的Rust代碼如下:

let p:Person = match serde_json::from_str(json_string) {
    Ok(p) => p,
    Err(e) => ... //we will discuss what goes here next 
};

正常情況下可以得到期望的結果。不過假設在輸入的json_string中有一個筆誤,這導致程序運行時將執行Err分支。

當碰到Err時,我們可以采取兩個動作:

  • panic!

  • 返回Err

3、unwrap - 故障時執行panic!

在上面的示例中,假設我們期望panic!:

let p: Person = match serde_json::from_str(data) {
        Ok(p) => p,
        Err(e) => panic!("cannot parse JSON {:?}, e"), //panic
    }

當碰到Err時,上面的代碼panic!就會崩掉整個程序,也許這不是你期望的。我們可以修改為:

let p:Person = serde_json::from_str(data).unwrap();

如果我們可以確定輸入的json_string始終會是可解析的,那么使用unwrap沒有問題。但是如果會出現Err,那么程序就會崩潰,無法從故障中恢復。在開發過程中,當我們更關心程序的主流程時,unwrap也可以作為快速 原型使用。

因此unwrap隱含了panic!。雖然與更顯式的版本沒有差異,但是危險在于其隱含特性,因為有時這并不是你真正期望的行為。

無論如何,如果我們需要調用panic!,代碼如下:

use serde::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    phones: Vec<String>,
}

fn typed_example() -> Result<()> {
    //age2 is error on purpose
    let data = r#"
        {
            "name": "John Doe",
            "age2": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    let p:Person = serde_json::from_str(data).unwrap();

    println!("Please call {} at the number {}", p.name, p.phones[0]);

    Ok(())
}

fn main() {
    match typed_example() {
        Ok(_) => println!("program ran ok"),
        Err(_) => println!("program ran with error"),
    }
}

4、? - 故障時返回Err對象

當碰到Err時,我們不一定要panic!,也可以返回Err。不是每個Err都是不可恢復的,因此有時并不需要panic!。下面的代碼返回Err:

let p: Person = match serde_json::from_str(data) {
        Ok(p) => p,
        Err(e) => return Err(e.into()),
};

?操作符提供了一個更簡潔的方法來替換上面的代碼:

let p:Person = serde_json::from_str(data)?;

這時完整的Rust程序代碼如下:

use serde::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    phones: Vec<String>,
}

fn typed_example() -> Result<()> {
    //age2 is error on purpose
    let data = r#"
        {
            "name": "John Doe",
            "age2": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    let p: Person = serde_json::from_str(data)?;

    println!("Please call {} at the number {}", p.name, p.phones[0]);

    Ok(())
}

fn main() {
    match typed_example() {
        Ok(_) => println!("program ran ok"),
        Err(e) => println!("program ran with error {:?}", e),
    }
}

5、使用unwrap和?解包Option

就像我們可以使用unwarp和?來處理Result,我們也可以使用unwrap和?來處理Option。

如果我們unwrap的Option的值是None,那么程序就會panic!。示例如下:

fn next_birthday(current_age: Option<u8>) -> Option<String> {
	// If `current_age` is `None`, this returns `None`.
	// If `current_age` is `Some`, the inner `u8` gets assigned to `next_age` after 1 is added to it
    let next_age: u8 = current_age?;
    Some(format!("Next year I will be {}", next_age + 1))
}

fn main() {
  let s = next_birthday(None);
  match s {
      Some(a) => println!("{:#?}", a),
      None => println!("No next birthday")
  }
}

到此,相信大家對“Result/Option/unwrap/的概念是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

江津市| 曲阜市| 敦化市| 康保县| 东兴市| 定边县| 南乐县| 安图县| 泽普县| 全椒县| 宕昌县| 长岭县| 桑日县| 临江市| 乌鲁木齐市| 连江县| 竹溪县| 芒康县| 乌兰察布市| 堆龙德庆县| 东安县| 古蔺县| 阿拉尔市| 包头市| 密山市| 福安市| 益阳市| 固始县| 浦城县| 武邑县| 托里县| 广安市| 台前县| 石台县| 油尖旺区| 叙永县| 新昌县| 贡觉县| 潜山县| 平罗县| 兰西县|