欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入了解Rust中的枚舉和模式匹配

 更新時(shí)間:2024年01月11日 09:41:49   作者:二次元攻城獅  
這篇文章主要為大家詳細(xì)介紹了Rust中的枚舉和模式匹配的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

枚舉的定義

結(jié)構(gòu)體可以將字段和數(shù)據(jù)聚合在一起,而枚舉可以將一個(gè)值成為一個(gè)集合之一。

定義一個(gè) IpAddrKind 枚舉:

enum IpAddrKind {
    V4,
    V6,
}

枚舉值

創(chuàng)建 IpAddrKind 兩個(gè)不同成員的實(shí)例:

let four = IpAddrKind::V4;
let six = IpAddrKind::V6;

注意:枚舉的成員位于其標(biāo)識(shí)符的命名空間中,并使用兩個(gè)冒號(hào)分開。

定義一個(gè)函數(shù)來(lái)獲取任何 IpAddrKind,可以使用任一成員來(lái)調(diào)用這個(gè)函數(shù):

fn route(ip_kind: IpAddrKind) {}
route(IpAddrKind::V4);
route(IpAddrKind::V6);

將數(shù)據(jù)直接放進(jìn)每一個(gè)枚舉成員

將 IP 地址的數(shù)據(jù)和 IpAddrKind 成員存儲(chǔ)在一個(gè) struct 中,關(guān)聯(lián)枚舉成員與值:

enum IpAddrKind {
    V4,
    V6,
}

struct IpAddr {
    kind: IpAddrKind,
    address: String,
}

let home = IpAddr {
    kind: IpAddrKind::V4,
    address: String::from("127.0.0.1"),
};

let loopback = IpAddr {
    kind: IpAddrKind::V6,
    address: String::from("::1"),
};

可以使用一種更簡(jiǎn)潔的方式來(lái)表達(dá)相同的概念,僅僅使用枚舉并將數(shù)據(jù)直接放進(jìn)每一個(gè)枚舉成員而不是將枚舉作為結(jié)構(gòu)體的一部分。

IpAddr 枚舉的新定義表明了 V4 和 V6 成員都關(guān)聯(lián)了 String 值:

enum IpAddr {
    V4(String),
    V6(String),
}

let home = IpAddr::V4(String::from("127.0.0.1"));
let loopback = IpAddr::V6(String::from("::1"));

IpAddr::V4() 是一個(gè)獲取 String 參數(shù)并返回 IpAddr 類型實(shí)例的函數(shù)調(diào)用,這些構(gòu)造函數(shù)會(huì)自動(dòng)被定義。

將不同類型和數(shù)量的數(shù)據(jù)放入枚舉成員

用枚舉替代結(jié)構(gòu)體還有另一個(gè)優(yōu)勢(shì):每個(gè)成員可以處理不同類型和數(shù)量的數(shù)據(jù)。枚舉則可以輕易的處理這個(gè)情況:

enum IpAddr {
    V4(u8, u8, u8, u8),  //V4 地址存儲(chǔ)為四個(gè) u8 值
    V6(String),          //V6 地址存儲(chǔ)為一個(gè) String
}
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));

存儲(chǔ)和編碼 IP 地址實(shí)在是太常見了,標(biāo)準(zhǔn)庫(kù)提供了一個(gè)開箱即用的定義:

struct Ipv4Addr {
    // --snip--
}

struct Ipv6Addr {
    // --snip--
}

enum IpAddr {
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}

這說(shuō)明可以將任意類型的數(shù)據(jù)放入枚舉成員中:例如字符串、數(shù)字類型或者結(jié)構(gòu)體,甚至可以包含另一個(gè)枚舉。

有關(guān)聯(lián)值的枚舉和結(jié)構(gòu)體的相似性

一個(gè) Message 枚舉,其每個(gè)成員都存儲(chǔ)了不同數(shù)量和類型的值:

enum Message {
    Quit,                       //Quit 沒有關(guān)聯(lián)任何數(shù)據(jù)
    Move { x: i32, y: i32 },    //Move 類似結(jié)構(gòu)體包含命名字段
    Write(String),              //Write 包含單獨(dú)一個(gè) String
    ChangeColor(i32, i32, i32), //ChangeColor 包含三個(gè) i32
}

如下結(jié)構(gòu)體可以包含和上面枚舉成員相同的數(shù)據(jù),但它們都有不同的類型:

struct QuitMessage; // 類單元結(jié)構(gòu)體
struct MoveMessage {
    x: i32,
    y: i32,
}
struct WriteMessage(String); // 元組結(jié)構(gòu)體
struct ChangeColorMessage(i32, i32, i32); // 元組結(jié)構(gòu)體

使用 impl 在枚舉上定義方法

可以使用 impl 在枚舉上定義方法,在 Message 枚舉上定義一個(gè)叫做 call 的方法:

impl Message {
    fn call(&self) {
        // 在這里定義方法體
    }
}

let m = Message::Write(String::from("hello"));
m.call();

方法體使用了 self 來(lái)獲取調(diào)用方法的值,上面的變量 m 就是當(dāng) m.call() 運(yùn)行時(shí) call 方法中的 self 的值。

Option 枚舉和其相對(duì)于空值的優(yōu)勢(shì)

Option 是標(biāo)準(zhǔn)庫(kù)定義的一個(gè)枚舉,它編碼了一個(gè)非常普遍的場(chǎng)景:一個(gè)值要么有值要么沒值。

Rust 沒有空值功能,空值(Null )是一個(gè)值,它代表沒有值。在有空值的語(yǔ)言中,變量總是這兩種狀態(tài)之一:空值和非空值。

Rust 并沒有空值,不過(guò)它確實(shí)擁有一個(gè)可以編碼存在或不存在概念的枚舉 Option<T>,而且它定義于標(biāo)準(zhǔn)庫(kù)中,如下:

enum Option<T> {
    None,
    Some(T),
}

Option 枚舉包含在 prelude 之中不需要將其顯式引入作用域,它的成員也可以不需要 Option:: 前綴來(lái)直接使用 Some 和 None。

一些包含數(shù)字類型和字符串類型 Option 值的例子:

//根據(jù)Some 成員的值推斷變量類型
let some_number = Some(5); //some_number 的類型是 Option<i32>
let some_char = Some('e'); //some_char 的類型是 Option<char>
//需要顯示指定 Option 整體的類型 為 Option<i32>
let absent_number: Option<i32> = None;

因?yàn)?Option 和 T(這里 T 可以是任何類型)是不同的類型,編譯器不允許像一個(gè)肯定有效的值那樣使用 Option:
代碼嘗試將 Option 與 i8 相加,無(wú)法通過(guò)編譯:

let x: i8 = 5;
let y: Option<i8> = Some(5);
//錯(cuò)誤,無(wú)法通過(guò)編譯!
let sum = x + y;

在對(duì) Option 進(jìn)行運(yùn)算之前必須將其轉(zhuǎn)換為 T,這能幫助我們捕獲到空值最常見的問題之一:假設(shè)某值不為空但實(shí)際上為空的情況。

為了使用 Option 值,需要編寫處理每個(gè)成員的代碼。match 表達(dá)式就是這么一個(gè)處理枚舉的控制流結(jié)構(gòu):它會(huì)根據(jù)枚舉的成員運(yùn)行不同的代碼,這些代碼可以使用匹配到的值中的數(shù)據(jù):

let some_value: Option<i32> = Some(42);
match some_value {
    Some(value) => {
        println!("The value is: {}", value);
        // 在這里可以使用 value
    }
    None => {
        println!("The value is None");
        // 處理 None 的情況
    }
}

match 控制流結(jié)構(gòu)

Rust 有一個(gè)叫做 match 的極為強(qiáng)大的控制流運(yùn)算符,它允許我們將一個(gè)值與一系列的模式相比較,并根據(jù)相匹配的模式執(zhí)行相應(yīng)代碼。

注:模式可由字面值、變量、通配符和許多其他內(nèi)容構(gòu)成。

編寫一個(gè)函數(shù)來(lái)獲取一個(gè)未知的硬幣,并以一種類似驗(yàn)鈔機(jī)的方式,確定它是何種硬幣并返回它的美分值:

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        //如果想要在分支中運(yùn)行多行代碼,可以使用大括號(hào),而分支后的逗號(hào)是可選的
        Coin::Penny => {
            println!("Lucky penny!");
            1
        }
        //果分支代碼較短的話通常不使用大括號(hào)
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

每個(gè)分支相關(guān)聯(lián)的代碼是一個(gè)表達(dá)式,而表達(dá)式的結(jié)果值將作為整個(gè) match 表達(dá)式的返回值。

綁定值的模式

匹配分支的另一個(gè)有用的功能是可以綁定匹配的模式的部分值,這也就是如何從枚舉成員中提取值的。

改變 Quarter 成員來(lái)包含一個(gè) State 值:

#[derive(Debug)] // 這樣可以立刻看到州的名稱
enum UsState {
    Alabama,
    Alaska,
    // --snip--
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

在匹配 Coin::Quarter 成員的分支的模式中增加了一個(gè)叫做 state 的變量,當(dāng)匹配到 Coin::Quarter 時(shí)變量 state 將會(huì)綁定對(duì)應(yīng)州的值:

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter(state) => {
            println!("State quarter from {:?}!", state);
            25
        }
    }
}

匹配 Option<T>

在 Option<i32> 上使用 match 表達(dá)式的函數(shù):

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        //i 綁定了 Some 中包含的值
        Some(i) => Some(i + 1),
    }
}
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);

將 match 與枚舉相結(jié)合在很多場(chǎng)景中都是有用的,Rust 代碼中有很多這樣的模式:match 一個(gè)枚舉,綁定其中的值到一個(gè)變量,接著根據(jù)其值執(zhí)行代碼。

匹配是窮盡的

以下代碼沒有處理 None 的情況,無(wú)法通過(guò)編譯:

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        Some(i) => Some(i + 1),
    }
}

Rust 中的匹配是 窮盡的(exhaustive):必須窮舉到最后的可能性來(lái)使代碼有效。

通配模式和 _ 占位符

對(duì)一些特定的值采取特殊操作,而對(duì)其他的值采取默認(rèn)操作,模式 other 涵蓋了所有其他可能的值:

let dice_roll = 9;
match dice_roll {
    3 => add_fancy_hat(),
    7 => remove_fancy_hat(),
    other => move_player(other),
}
fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn move_player(num_spaces: u8) {}

當(dāng)不想使用通配模式獲取的值時(shí),請(qǐng)使用 _ ,這是一個(gè)特殊的模式,可以匹配任意值而不綁定到該值:

let dice_roll = 9;
match dice_roll {
    3 => add_fancy_hat(),
    7 => remove_fancy_hat(),
    _ => reroll(),  //或者 _ => (),
}

fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn reroll() {}

if let 簡(jiǎn)潔控制流

可以認(rèn)為 if let 是 match 的一個(gè)語(yǔ)法糖,它當(dāng)值匹配某一模式時(shí)執(zhí)行代碼而忽略所有其他值。

match 只關(guān)心當(dāng)值為 Some 時(shí)執(zhí)行代碼:

let config_max = Some(3u8);
match config_max {
    Some(max) => println!("The maximum is configured to be {}", max),
    _ => (),
}

可以使用 if let 這種更短的方式編寫:

let config_max = Some(3u8);
if let Some(max) = config_max {
    println!("The maximum is configured to be {}", max);
}

可以在 if let 中包含一個(gè) else。else 塊中的代碼與 match 表達(dá)式中的 _ 分支塊中的代碼相同,這樣的 match 表達(dá)式就等同于 if let 和 else。

使用 match 表達(dá)式:

let mut count = 0;
match coin {
    Coin::Quarter(state) => println!("State quarter from {:?}!", state),
    _ => count += 1,
}

使用 if let 和 else 表達(dá)式:

let mut count = 0;
if let Coin::Quarter(state) = coin {
    println!("State quarter from {:?}!", state);
} else {
    count += 1;
}

以上就是深入了解Rust中的枚舉和模式匹配的詳細(xì)內(nèi)容,更多關(guān)于Rust枚舉和模式匹配的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Rust?編程語(yǔ)言中的所有權(quán)ownership詳解

    Rust?編程語(yǔ)言中的所有權(quán)ownership詳解

    這篇文章主要介紹了Rust?編程語(yǔ)言中的所有權(quán)ownership詳解的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • 深入了解Rust中trait的使用

    深入了解Rust中trait的使用

    先前我們提到過(guò)?trait,那么Rust中的trait?是啥呢?本文將通過(guò)一些示例為大家詳細(xì)講講Rust中trait的使用,感興趣的小伙伴可以了解一下
    2022-11-11
  • rust標(biāo)準(zhǔn)庫(kù)std::env環(huán)境相關(guān)的常量

    rust標(biāo)準(zhǔn)庫(kù)std::env環(huán)境相關(guān)的常量

    在本章節(jié)中, 我們探討了Rust處理命令行參數(shù)的常見的兩種方式和處理環(huán)境變量的兩種常見方式, 拋開Rust的語(yǔ)法, 實(shí)際上在命令行參數(shù)的處理方式上, 與其它語(yǔ)言大同小異, 可能影響我們習(xí)慣的也就只剩下語(yǔ)法,本文介紹rust標(biāo)準(zhǔn)庫(kù)std::env的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2024-03-03
  • 深入了解Rust中的枚舉和模式匹配

    深入了解Rust中的枚舉和模式匹配

    這篇文章主要為大家詳細(xì)介紹了Rust中的枚舉和模式匹配的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • 使用win10 wsl子系統(tǒng)如何將 rust 程序靜態(tài)編譯為linux可執(zhí)行文件

    使用win10 wsl子系統(tǒng)如何將 rust 程序靜態(tài)編譯為linux可執(zhí)行文件

    這篇文章主要介紹了使用win10 wsl子系統(tǒng)如何將 rust 程序靜態(tài)編譯為linux可執(zhí)行文件,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2025-05-05
  • Rust 中解析 JSON的方法

    Rust 中解析 JSON的方法

    要開始在 Rust 中使用 JSON,您需要安裝一個(gè)可以輕松操作 JSON 的庫(kù),目前可用的流行crate之一是 serde-json,在本文中,我們將討論如何在 Rust 中使用 JSON 解析庫(kù),以及比較最流行的庫(kù)及其性能
    2024-03-03
  • Rust中GUI庫(kù)egui的簡(jiǎn)單應(yīng)用指南

    Rust中GUI庫(kù)egui的簡(jiǎn)單應(yīng)用指南

    egui(發(fā)音為“e-gooey”)是一個(gè)簡(jiǎn)單、快速且高度可移植的 Rust 即時(shí)模式 GUI 庫(kù),跨平臺(tái)、Rust原生,適合一些小工具和游戲引擎GUI,下面就跟隨小編一起來(lái)看看它的具體使用吧
    2024-03-03
  • Rust遍歷 BinaryHeap的示例代碼

    Rust遍歷 BinaryHeap的示例代碼

    Rust 的 BinaryHeap 結(jié)構(gòu)體實(shí)現(xiàn)了迭代器接口,因此你可以遍歷它,如果你想要遍歷 BinaryHeap 中的所有元素,你可以使用 .into_iter() 方法將其轉(zhuǎn)換為迭代器,并遍歷其中的元素,本文通過(guò)實(shí)例介紹Rust遍歷 BinaryHeap的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2024-04-04
  • 解析Rust?struct?中的生命周期

    解析Rust?struct?中的生命周期

    rust?的生命周期保證了內(nèi)存的安全性,同時(shí)也增加了開發(fā)者的心智負(fù)擔(dān)。是在上線之前多費(fèi)心思寫代碼,還是在上線以后忙忙活活查問題,這是個(gè)?trade?off?問題,這篇文章主要介紹了Rust?struct?中的生命周期,需要的朋友可以參考下
    2022-10-10
  • 使用Rust實(shí)現(xiàn)日志記錄功能

    使用Rust實(shí)現(xiàn)日志記錄功能

    這篇文章主要為大家詳細(xì)介紹了使用Rust實(shí)現(xiàn)日志記錄功能的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的可以參考一下
    2024-04-04

最新評(píng)論