【Rust】05-结构体、枚举与模式匹配

结构体、枚举与模式匹配

学习目标

  • 使用结构体组织相关数据。
  • 使用枚举表达有限状态。
  • 掌握 matchif let 的基本用法。

结构体

结构体用于给一组相关字段命名:

rust 复制代码
struct User {
    name: String,
    email: String,
    active: bool,
}

fn main() {
    let user = User {
        name: String::from("Alice"),
        email: String::from("alice@example.com"),
        active: true,
    };

    println!("{} <{}>", user.name, user.email);
}

字段默认不可变。如果需要修改字段,整个结构体绑定必须是 mut

rust 复制代码
let mut user = User {
    name: String::from("Alice"),
    email: String::from("alice@example.com"),
    active: true,
};

user.active = false;

Rust 不支持只把某个字段标记为可变。

字段初始化简写

当变量名和字段名相同时,可以简写:

rust 复制代码
struct User {
    name: String,
    email: String,
}

fn build_user(name: String, email: String) -> User {
    User { name, email }
}

结构体更新语法

可以基于已有结构体创建新值:

rust 复制代码
struct Settings {
    theme: String,
    page_size: u32,
    notifications: bool,
}

fn main() {
    let default = Settings {
        theme: String::from("light"),
        page_size: 20,
        notifications: true,
    };

    let custom = Settings {
        theme: String::from("dark"),
        ..default
    };

    println!("{}", custom.theme);
}

注意:如果被移动的字段不是 Copy,使用 ..default 后,default 可能不再完整可用。

方法

使用 impl 给结构体定义方法:

rust 复制代码
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    let rect = Rectangle {
        width: 30,
        height: 50,
    };

    println!("{}", rect.area());
}

&selfself: &Self 的简写,表示方法借用当前实例。

枚举

枚举用于表达一个值只能是若干变体之一:

rust 复制代码
enum Direction {
    Up,
    Down,
    Left,
    Right,
}

枚举变体可以携带数据:

rust 复制代码
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(u8, u8, u8),
}

这让枚举非常适合表达状态机、命令、协议消息和错误类型。

match

match 会穷尽处理所有可能分支:

rust 复制代码
enum Direction {
    Up,
    Down,
    Left,
    Right,
}

fn describe(direction: Direction) -> &'static str {
    match direction {
        Direction::Up => "go up",
        Direction::Down => "go down",
        Direction::Left => "go left",
        Direction::Right => "go right",
    }
}

如果遗漏某个分支,编译器会报错。

if let

当只关心一个模式时,可以使用 if let

rust 复制代码
fn main() {
    let value = Some(3);

    if let Some(number) = value {
        println!("number={number}");
    }
}

这比只为了处理一个分支写完整 match 更简洁。

常见误区

  • 结构体字段可变性由变量绑定决定,不由字段单独决定。
  • match 必须穷尽所有情况,这是优点,不是麻烦。
  • 枚举不是只能表示无数据标签;它的变体可以携带不同形状的数据。
  • if let 适合单分支,复杂逻辑仍建议使用 match

练习

  1. 定义一个 Book 结构体,包含标题、作者和页数。
  2. Book 实现一个 summary 方法。
  3. 定义一个 TaskStatus 枚举,包含 TodoDoingDone,用 match 打印状态说明。

后记

2026年6月10日17点14分于上海。

相关推荐
倔强的石头_1 小时前
《Kingbase护城河》——猎捕慢查询:执行计划的微观解析与索引调优实战
数据库
SelectDB3 小时前
Apache Doris Python UDF:让 SQL 直接调用 Python 生态,支撑 Agent 时代复杂业务逻辑
大数据·数据库·python
Flittly4 小时前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了5 小时前
Java 生成二维码解决方案
java·后端
人活一口气9 小时前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot
NE_STOP11 小时前
Vibe Coding -- 完整项目案例实操
java
荣码11 小时前
GraphRAG:普通RAG只能回答"点"的问题,我踩了4个坑才搞懂
java·python
SimonKing11 小时前
Google第三方授权登录
java·后端·程序员
独孤留白11 小时前
从C到Rust:Rust 的 Trait 不是Interface,那是什么?
rust
明月光81811 小时前
从一行 @Builder 说起:重新拾起 Java 的 Lombok、注解与 Builder 模式
java