Rust 強調記憶體安全和效能,提供結構體、列舉等資料結構。結構體能定義不同型別欄位,例如座標或尺寸。元組結構體則結合結構體和元組特性,賦予型別名稱但欄位無名。列舉定義一組具名值,適用於 HTTP 狀態碼等互斥值,能提升程式碼可讀性及安全性。列舉的變體可攜帶資料,使其成為集合型別和代數資料型別,可用於避免無效狀態。

函式是程式碼的 reusable 區塊,可接收引數,方法則與特定資料結構關聯,類別似物件導向概念,但 Rust 的方法也能新增到列舉。函式指標提供間接層,閉包則源自 Lisp,現已廣泛應用,特徵描述相關功能集合,類別似 C++ 的抽象類別或 Java 的介面。Rust 標準函式庫提供 Option 和 Result 列舉,分別處理可能不存在的值和操作結果。Option 有 Some(T) 和 None 變體,Result 則有 Ok(T) 和 Err(E) 變體。

元組

元組是一種 Aggregate 型別,可以儲存多個不同型別的值。例如, (WidgetOffset, WidgetSize, WidgetColor) 代表了一個包含三個不同型別值的元組。

結構體(Structs)和列舉(Enums)在Rust中的應用

Rust是一種強調記憶體安全和效能的程式語言,它提供了多種資料結構來幫助開發者組織和管理資料。其中,結構體(Structs)和列舉(Enums)是兩種基本的資料結構。

結構體(Structs)

結構體是一種複合資料型別,允許你定義一組具有不同型別的欄位。結構體可以用來代表實際世界中的物體或概念,例如一個點的座標、一個矩形的尺寸等。以下是一個簡單的結構體定義範例:

struct Point {
    x: i32,
    y: i32,
}

你可以建立一個結構體例項並存取其欄位:

let point = Point { x: 1, y: 2 };
println!("x: {}, y: {}", point.x, point.y);

Rust還提供了一種特殊的結構體,稱為元組結構體(Tuple Struct),它結合了結構體和元組的特點。元組結構體允許你定義一個具有名稱的型別,但其欄位沒有名稱。以下是一個元組結構體定義範例:

struct TextMatch(usize, String);

你可以建立一個元組結構體例項並存取其欄位:

let m = TextMatch(12, "needle".to_owned());
println!("index: {}, text: {}", m.0, m.1);

列舉(Enums)

列舉是一種特殊的資料型別,允許你定義一組具有名稱的值。列舉可以用來代表一組互斥的值,例如HTTP狀態碼、顏色等。以下是一個簡單的列舉定義範例:

enum HttpResultCode {
    Ok = 200,
    NotFound = 404,
    Teapot = 418,
}

你可以使用列舉值並存取其相關聯的數值:

let code = HttpResultCode::NotFound;
println!("code: {}", code as i32);

列舉還可以用來改善函式的可讀性和維護性。例如,你可以定義兩個列舉,分別代表列印頁面的兩個方面:SidesOutput

enum Sides {
    Both,
    Single,
}

enum Output {
    BlackAndWhite,
    Color,
}

然後,你可以定義一個函式,接受這兩個列舉作為引數:

pub fn print_page(sides: Sides, color: Output) {
    //...
}

這樣,你就可以以更清晰和安全的方式呼叫函式:

print_page(Sides::Both, Output::BlackAndWhite);

如果你不小心調換了引數的順序,編譯器會立即報錯:

error[E0308]: arguments to this function are incorrect
 --> src/main.rs:104:9
 |
104 | print_page(Output::BlackAndWhite, Sides::Single);
 | ^^^^^^^^^^ --------------------- ------------- expected `enums::Output`,
 | | found `enums::Sides`
 |
note: function defined here
 --> src/main.rs:145:12
 |
145 | pub fn print_page(sides: Sides, color: Output) {
 | ^^^^^^^^^^ ------------ -------------
help: swap these arguments
 |
104 | print_page(Sides::Single, Output::BlackAndWhite);

使用Rust的列舉和匹配表示式實作型別安全

在Rust中,列舉(enum)是一種強大的工具,能夠幫助我們實作型別安全和可維護性。透過使用列舉,我們可以定義一組相關的值,並確保這些值之間的關係是明確的。

例如,假設我們想要定義一組HTTP結果碼,我們可以使用列舉來實作:

enum HttpResultCode {
    Ok,
    NotFound,
    Teapot = 418,
}

在這個例子中,我們定義了一個名為HttpResultCode的列舉,它包含三個變體:OkNotFoundTeapot。注意,Teapot變體的值為418,這是一個特殊的HTTP結果碼。

現在,假設我們想要根據HTTP結果碼傳回一個字串訊息,我們可以使用匹配表示式(match expression)來實作:

let msg = match code {
    HttpResultCode::Ok => "Ok",
    HttpResultCode::NotFound => "Not found",
    HttpResultCode::Teapot => "I'm a teapot",
};

在這個例子中,我們使用匹配表示式來根據code變數的值傳回一個字串訊息。如果code的值為HttpResultCode::Ok,則傳回字串"Ok";如果code的值為HttpResultCode::NotFound,則傳回字串"Not found";如果code的值為HttpResultCode::Teapot,則傳回字串"I’m a teapot"。

Rust的列舉和匹配表示式提供了強大的型別安全性和可維護性。如果我們忘記處理某個變體,Rust編譯器將會報錯並提示我們新增缺失的變體。

列舉的優點

使用列舉有以下優點:

  • 型別安全:列舉可以幫助我們確保程式碼中的值是有效的和安全的。
  • 可維護性:列舉可以幫助我們維護程式碼的可讀性和可維護性。
  • 擴充套件性:列舉可以幫助我們輕鬆地新增新的變體和功能。

瞭解Rust的列舉(enum)及其在資料結構中的應用

Rust的列舉(enum)是一種強大的工具,能夠讓開發者以型別安全的方式定義資料結構。列舉允許每個變體(variant)攜帶資料,使其成為了一種集合型別(aggregate type),同時也是一種代數資料型別(algebraic data type,ADT)。

列舉的定義和應用

以下是定義一個簡單的列舉SchedulerState的例子:

pub enum SchedulerState {
    Inert,
    Pending(HashSet<Job>),
    Running(HashMap<CpuId, Vec<Job>>),
}

這個列舉定義了三個變體:InertPendingRunning。每個變體都有不同的資料結構:Inert沒有任何資料,Pending攜帶一個HashSet,而Running攜帶一個HashMap

使用列舉來避免無效狀態

列舉可以用來避免無效狀態的出現。例如,下面的結構體DisplayProps有一個欄位fg_color,其有效性取決於另一個欄位monochrome

pub struct DisplayProps {
    pub x: u32,
    pub y: u32,
    pub monochrome: bool,
    // `fg_color` 必須為 (0, 0, 0) 如果 `monochrome` 是 true。
    pub fg_color: RgbColor,
}

這種設計容易導致錯誤,因為開發者可能會忘記檢查monochrome的值。使用列舉可以更好地解決這個問題:

pub enum Color {
    Monochrome,
    Foreground(RgbColor),
}

pub struct DisplayProps {
    pub x: u32,
    pub y: u32,
    pub color: Color,
}

這樣設計可以確保無效狀態(例如,當monochrome為true時,fg_color不是(0, 0, 0))在編譯時就被檢查出來。

Option和Result列舉

Rust標準函式庫中還提供了兩種常用的列舉:OptionResult

  • Option用於表示一個值可能存在也可能不存在。它有兩個變體:Some(T)None

  • Result用於表示一個操作可能成功或失敗。它有兩個變體:Ok(T)Err(E),分別表示成功和失敗。

這兩種列舉在Rust中非常常用,可以幫助開發者以型別安全的方式處理可能出錯的操作或可能不存在的值。

函式和方法:程式設計的基礎

在程式設計中,函式是一種將程式碼組織成可重複使用的塊,並能夠接收引數的機制。函式可以獨立存在,也可以與特定的資料結構相關聯,在後者情況下,它們被稱為方法。

函式

函式是將一段程式碼與一個名稱和引數列表相關聯的通用機制。它們是程式設計中的一個基本概念,允許程式碼的重用和模組化。以下是Rust中定義一個函式的例子:

/// 傳回 `x` 除以 `y` 的結果。
fn div(x: f64, y: f64) -> f64 {
    if y == 0.0 {
        // 終止函式並傳回一個值。
        return f64::NAN;
    }
    // 函式體中的最後一個表示式被隱式傳回。
    x / y
}

/// 一個只為了副作用而呼叫的函式,沒有傳回值。
/// 也可以寫成 `-> ()`。
fn show(x: f64) {
    println!("x = {x}");
}

方法

如果一個函式與特定的資料結構密切相關,它可以被表達為該資料結構的一個方法。方法作用於該型別的專案上,並包含在 impl 資料結構 區塊中。這種方式封裝了相關的資料和程式碼,類別似於其他語言中的物件導向方式,但在Rust中,方法也可以新增到列舉型別上,而不僅僅是結構體型別。

enum Shape {
    Rectangle { width: f64, height: f64 },
    Circle { radius: f64 },
}

impl Shape {
    pub fn area(&self) -> f64 {
        match self {
            Shape::Rectangle { width, height } => width * height,
            Shape::Circle { radius } => std::f64::consts::PI * radius * radius,
        }
    }
}

在這個例子中,area 方法是 Shape 列舉的一部分,它計算形狀的面積。方法的名稱提供了一個對其行為的標籤,而方法簽名則給出了輸入和輸出的型別資訊。對於方法,第一個輸入通常是某種形式的 self,指示方法可能對資料結構做什麼。

函式指標、閉包和特徵

除了函式和方法之外,Rust還支援函式指標、閉包和特徵等其他機制。函式指標允許在呼叫其他程式碼時新增一層間接層。閉包最初在Lisp家族的語言中很常見,但現在已被移植到包括C++和Java在內的許多流行語言中。特徵描述了一組適用於相同底層專案的相關功能集合,它們在其他語言中有相應的抽象概念,例如C++中的抽象類別和Go及Java中的介面。

圖表翻譯:

  graph LR
    A[函式] --> B[方法]
    B --> C[函式指標]
    C --> D[閉包]
    D --> E[特徵]
    E --> F[資料結構]
    F --> G[列舉]
    G --> H[結構體]

這個圖表展示了Rust中不同程式設計機制之間的關係,包括函式、方法、函式指標、閉包、特徵,以及它們與資料結構、列舉和結構體的關係。

從技術架構視角來看,Rust 的結構體(Structs)和列舉(Enums)提供強大的資料建模能力。深入剖析其核心設計,可以發現列舉結合模式匹配,有效提升了程式碼的表達力和安全性,避免了無效狀態的產生,例如 Option 和 Result 的應用,顯著降低了錯誤處理的複雜度。同時,結構體與方法的結合,則提供了類別似物件導向程式設計的封裝性和程式碼組織能力,提升程式碼的可讀性和可維護性。然而,Rust 的所有權和借用規則在使用這些資料結構時需要格外注意,這也增加了初學者的學習曲線。對於追求效能和記憶體安全的系統級程式設計,Rust 的 Structs 和 Enums 配合模式匹配和方法機制,提供了更為精確和可靠的解決方案。從技術演進角度,Rust 的型別系統和所有權機制對程式碼安全性的提升,代表了現代系統程式語言的一個重要發展方向。對於注重程式碼品質和長期維護的團隊,Rust 值得深入研究和應用。玄貓認為,Rust 的學習曲線雖然較陡峭,但其帶來的效能和安全優勢,在特定領域,例如嵌入式系統、作業系統和高效能運算等,將使其成為不可或缺的程式語言。