【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分于上海。

相关推荐
guodingdingh1 小时前
软件开发工作问题总结0718
java·开发语言·数据库
花褪残红青杏小1 小时前
Rust图像处理第20节-PCA 主成分分析:把图片压缩到 3 个数字
rust·webassembly·图形学
咖啡八杯3 小时前
GoF设计模式——解释器模式
java·后端·spring·设计模式
GuWenyue3 小时前
Cursor黑盒拆解!1套LangChain.js手写Mini编程Agent,自动生成React项目,效率提升60%
前端·数据库·人工智能
优橙教育3 小时前
5G网优培训 vs Java开发:转行选哪个?
java·开发语言·5g
糖果店的幽灵3 小时前
【DeepAgents 从入门到精通】Context Management 上下文管理
java·人工智能·后端·spring·中间件·langgraph·deepagents
腻害兔5 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
Miao121315 小时前
某海外住宿平台如何在大规模场景下实现指标一致性:Minerva 指标平台实践
大数据·数据库·人工智能
CodexDave5 小时前
MySQL事务隔离级别与MVCC机制解析
前端·数据库·mysql·nginx·性能优化·负载均衡
碎光拾影5 小时前
ARM交叉工具链各工具作用及IMX6ULL平台LED+蜂鸣器裸机程序实现
java·开发语言·数据库