《Rust快速入门》6. 结构体与枚举

结构体与枚举:Rust 中的自定义数据类型 Rust 提供了结构体(struct)和枚举(enum)两种强大的自定义数据类型。结构体用于组织和存储相关数据,而枚举则用于定义一组可能的值。结合模式匹配,结构体和枚举可以极大地增强代码的表达能力和安全性。本文将详细介绍结构体和枚举的定义与使用,并深入探讨模式匹配的高级用法。 …

结构体与枚举:Rust 中的自定义数据类型

Rust 提供了结构体(struct)和枚举(enum)两种强大的自定义数据类型。结构体用于组织和存储相关数据,而枚举则用于定义一组可能的值。结合模式匹配,结构体和枚举可以极大地增强代码的表达能力和安全性。本文将详细介绍结构体和枚举的定义与使用,并深入探讨模式匹配的高级用法。


1. 结构体

1.1 定义结构体

结构体是一种自定义数据类型,允许将多个相关的值组合在一起。结构体的定义使用 struct 关键字。

示例 1:定义一个简单的结构体

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

解释:

  • struct User { ... } 定义了一个名为 User 的结构体。
  • usernameemailsign_in_countactive 是结构体的字段,分别表示用户名、电子邮件、登录次数和激活状态。

1.2 实例化结构体

结构体定义后,可以通过指定字段的值来创建实例。

示例 2:创建结构体实例

fn main() {
    let user1 = User {
        username: String::from("alice"),
        email: String::from("alice@example.com"),
        sign_in_count: 1,
        active: true,
    };

    println!("Username: {}", user1.username);
    println!("Email: {}", user1.email);
    println!("Sign-in count: {}", user1.sign_in_count);
    println!("Active: {}", user1.active);
}

解释:

  • let user1 = User { ... }; 创建了一个 User 结构体的实例。
  • 通过 user1.usernameuser1.email 等方式访问结构体的字段。

1.3 可变结构体

如果希望修改结构体的字段,可以将实例声明为可变的。

示例 3:修改结构体字段

fn main() {
    let mut user1 = User {
        username: String::from("alice"),
        email: String::from("alice@example.com"),
        sign_in_count: 1,
        active: true,
    };

    user1.sign_in_count += 1;
    println!("Updated sign-in count: {}", user1.sign_in_count);
}

解释:

  • let mut user1 = User { ... }; 创建了一个可变的 User 实例。
  • user1.sign_in_count += 1; 修改了 sign_in_count 字段的值。

1.4 结构体更新语法

在创建新实例时,可以使用结构体更新语法从现有实例中复制字段。

示例 4:使用结构体更新语法

fn main() {
    let user1 = User {
        username: String::from("alice"),
        email: String::from("alice@example.com"),
        sign_in_count: 1,
        active: true,
    };

    let user2 = User {
        username: String::from("bob"),
        email: String::from("bob@example.com"),
        ..user1 // 复制 user1 的其他字段
    };

    println!("User2's sign-in count: {}", user2.sign_in_count);
}

解释:

  • ..user1 表示将 user1 的其他字段复制到 user2 中。
  • user2usernameemail 字段被显式设置,而 sign_in_countactive 字段从 user1 复制。

1.5 元组结构体

元组结构体是一种类似于元组的结构体,字段没有名称,只有类型。

示例 5:定义和使用元组结构体

struct Color(i32, i32, i32);

fn main() {
    let black = Color(0, 0, 0);
    println!("Black: ({}, {}, {})", black.0, black.1, black.2);
}

解释:

  • struct Color(i32, i32, i32); 定义了一个元组结构体 Color
  • let black = Color(0, 0, 0); 创建了一个 Color 实例。
  • 通过 black.0black.1 等方式访问元组结构体的字段。

2. 枚举

2.1 定义枚举

枚举是一种自定义数据类型,允许定义一组可能的值。枚举的定义使用 enum 关键字。

示例 6:定义一个简单的枚举

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

解释:

  • enum Message { ... } 定义了一个名为 Message 的枚举。
  • Quit 是一个没有关联数据的变体。
  • Move 是一个包含匿名结构体的变体。
  • Write 是一个包含 String 类型的变体。
  • ChangeColor 是一个包含三个 i32 类型字段的变体。

2.2 使用枚举

枚举的每个变体都可以通过模式匹配来处理。

示例 7:使用枚举变体

fn main() {
    let msg = Message::Write(String::from("hello"));

    match msg {
        Message::Quit => println!("Quit"),
        Message::Move { x, y } => println!("Move to ({}, {})", x, y),
        Message::Write(text) => println!("Write: {}", text),
        Message::ChangeColor(r, g, b) => println!("Change color to ({}, {}, {})", r, g, b),
    }
}

解释:

  • let msg = Message::Write(String::from("hello")); 创建了一个 Message 枚举的实例。
  • match msg { ... } 使用模式匹配处理枚举的每个变体。

2.3 Option 枚举

Rust 标准库中的 Option 枚举用于处理可能为空的值。

示例 8:使用 Option 枚举

fn main() {
    let some_number = Some(5);
    let none_number: Option<i32> = None;

    match some_number {
        Some(value) => println!("Some: {}", value),
        None => println!("None"),
    }

    match none_number {
        Some(value) => println!("Some: {}", value),
        None => println!("None"),
    }
}

解释:

  • Option<i32> 表示一个可能为 i32 类型值或 None 的枚举。
  • Some(value) 表示有值,None 表示无值。

3. 模式匹配进阶

3.1 嵌套模式匹配

模式匹配可以嵌套,用于处理复杂的数据结构。

示例 9:嵌套模式匹配

enum Shape {
    Circle(f64),
    Rectangle(f64, f64),
}

fn main() {
    let shape = Shape::Rectangle(3.0, 4.0);

    match shape {
        Shape::Circle(radius) => println!("Circle with radius {}", radius),
        Shape::Rectangle(width, height) => {
            println!("Rectangle with width {} and height {}", width, height)
        }
    }
}

解释:

  • Shape::Rectangle(width, height) 匹配 Rectangle 变体,并解构其字段。

3.2 模式匹配与守卫

模式匹配可以与 if 条件(守卫)结合使用,进一步过滤匹配。

示例 10:模式匹配与守卫

fn main() {
    let number = Some(7);

    match number {
        Some(x) if x > 5 => println!("Greater than 5: {}", x),
        Some(x) => println!("Less than or equal to 5: {}", x),
        None => println!("None"),
    }
}

解释:

  • Some(x) if x > 5 只有在 x 大于 5 时才会匹配。

3.3 if let 语法

if letmatch 的简化语法,用于处理单一模式匹配。

示例 11:使用 if let

fn main() {
    let number = Some(7);

    if let Some(x) = number {
        println!("Number: {}", x);
    } else {
        println!("None");
    }
}

解释:

  • if let Some(x) = number { ... } 只匹配 Some 变体。

4. 综合示例

以下是一个综合示例,展示了结构体、枚举和模式匹配的结合使用:

enum Event {
    Login { username: String },
    Logout { username: String },
    Message { from: String, to: String, content: String },
}

fn handle_event(event: Event) {
    match event {
        Event::Login { username } => println!("User {} logged in", username),
        Event::Logout { username } => println!("User {} logged out", username),
        Event::Message { from, to, content } => {
            println!("Message from {} to {}: {}", from, to, content)
        }
    }
}

fn main() {
    let event = Event::Message {
        from: String::from("alice"),
        to: String::from("bob"),
        content: String::from("Hello, Bob!"),
    };

    handle_event(event);
}

解释:

  • Event 枚举定义了三种事件类型。
  • handle_event 函数使用模式匹配处理每种事件类型。

5. 总结

结构体和枚举是 Rust 中强大的自定义数据类型。结构体用于组织和存储相关数据,而枚举用于定义一组可能的值。结合模式匹配,可以高效地处理复杂的数据结构和逻辑。掌握这些概念是编写高效、安全的 Rust 程序的关键。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页