Rust中的Enum与Struct详解

在 Rust 中,struct(结构体)和enum(枚举)是两种核心的自定义类型,分别用于组合相关数据表示互斥的可能性

结构体struct

struct用于将多个相关的值组合在一起,形成一个有意义的组

具名结构体(named strcut)

最常用的结构体形式,字段有明确的名称,可读性强,适合数据含义明确的场景。

  • 字段默认私有(仅当前模块内可见)
  • 通过impl实现关联函数(方法)
  • 通过..实现赋值(所有未指定的字段,全部替换为...对应变量中的):若字段为移动语义,所有权被移走
  • 通过trait实现多态(参见《Rust中的特征Trait》)
rust 复制代码
use std::fmt;

pub struct Person {
    pub name: String,
    age: u8,
    active: bool,
}

impl fmt::Display for Person {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Person {{ name: {}, age: {}, active: {} }}", self.name, self.age, self.active)
    }
}

fn main() {
    let alice = Person { name: String::from("Alice"), age: 30, active: true };
    let mike = Person { name: String::from("Mike"), ..alice };
    println!("person: {}", mike);

    // 解结构与..
    let Person { name, .. } = mike;
    println!("name: {}", name);
}

可见性

默认为私有,可通过pub修饰符修改:

修饰符 可见范围 说明
pub 全局可见(跨 crate) 完全公开
pub(crate) 整个当前 crate 内可见 库内部共享
pub(super) 父模块可见 子模块辅助函数
pub(in path) 指定模块路径内可见 最灵活的控制
(无修饰) 当前模块私有 默认私有

trait(继承/多态)

Rust 没有传统 OOP 的类继承(没有基类/子类)。用 trait + impl 来实现接口/多态。

trait定义方法签名集合,实现trait的类必须提供所有对应方法:

  • 静态分发(T: Trait)在编译期确定具体类型(单态化,性能好)。
  • 动态分发(&dyn TraitBox<dyn Trait>)通过虚函数表(vtable),在运行时分发(适合异构集合/插件式架构)。
rust 复制代码
trait Drawable {
    fn draw(&self);
}

struct Circle { radius: f64 }
struct Square { side: f64 }

impl Drawable for Circle {
    fn draw(&self) { println!("circle r={}", self.radius); }
}
impl Drawable for Square {
    fn draw(&self) { println!("square s={}", self.side); }
}

// 静态分发(泛型)
fn draw_all<T: Drawable>(items: &[T]) {
    for item in items { item.draw(); }
}

// 动态分发(trait object)
fn draw_box(items: &[Box<dyn Drawable>]) {
    for item in items { item.draw(); }
}

泛型与生命周期

结构体可以是泛型的(参见《Rust中的泛型Generics》),也可以带生命周期参数。

rust 复制代码
struct Holder<'a, T> { r: &'a T, val: T }
struct Pair<T, U>(T, U);

泛型说明:

特性 说明
struct Point<T> 定义泛型结构体
impl<T> Point<T> 为所有类型实现方法
impl Point<i32> 为特定类型实现方法
T: Display 泛型约束,要求类型实现Displaytrait
where T: Clone, U: Debug 泛型约束,更清晰的约束语法

元组结构体(tuple struct)

字段没有名称,仅通过位置区分,适合数据结构简单、字段含义可通过位置推断的场景。

rust 复制代码
// 元组结构体:通过位置区分(x, y)
struct Point(i32, i32);  

// 创建实例
let p1 = Point(3, 4);
// 访问字段(通过索引)
println!("x坐标:{}", p1.0);  // 输出:x坐标:3

单元结构体(unit struct)

一种不包含任何字段的结构体。它的定义形式类似于一个"空"的结构体:

  • 在内存中不占用任何空间(size_of::<UnitStruct>() == 0
  • 主要用于标记类型(表示 "存在性" 而非 "数据")
rust 复制代码
// 定义状态
pub struct Locked;
pub struct Unlocked;

// 门的结构,使用泛型参数表示状态
pub struct Door<TState> {
    id: u32,
    _state: std::marker::PhantomData<TState>,
}

// 只有 Locked 状态才能解锁
impl Door<Locked> {
    fn unlock(self) -> Door<Unlocked> {
        println!("门 {} 已解锁", self.id);
        Door {
            id: self.id,
            _state: std::marker::PhantomData,
        }
    }
}

// 只有 Unlocked 状态才能打开
impl Door<Unlocked> {
    fn open(&self) {
        println!("门 {} 打开", self.id);
    }
    
    fn lock(self) -> Door<Locked> {
        println!("门 {} 已上锁", self.id);
        Door {
            id: self.id,
            _state: std::marker::PhantomData,
        }
    }
}

pub fn test_door() {
    let door = Door::<Locked> {
        id: 101,
        _state: std::marker::PhantomData,
    };    
    
    let door = door.unlock(); // 状态转换
    door.open(); // Unlocked 状态可以打开
    
    let door = door.lock(); // 重新上锁
}

枚举(enum)

枚举的核心作用是定义一个类型,其值是有限的、互斥的几种可能变体(variants)之一。每个变体可以关联不同类型和数量的数据。

枚举通过enum关键字定义,每个变体可以是 "空" 的,也可以携带数据(类似元组或结构体)。

rust 复制代码
// 定义枚举:消息类型
enum Message {
    Quit,  // 无数据:退出消息
    Move { x: i32, y: i32 },  // 具名数据:移动到(x,y)
    Write(String),  // 元组数据:写入文本
    ChangeColor(i32, i32, i32),  // 元组数据:修改颜色(RGB)
}

// 创建枚举实例
let msg1 = Message::Quit;  // 退出消息
let msg2 = Message::Move { x: 10, y: 20 };  // 移动到(10,20)
let msg3 = Message::Write(String::from("hello"));  // 写入"hello"

模式匹配

枚举的核心用法是通过match表达式匹配其变体,从而处理不同情况(类似 "多分支条件判断",但更安全)。

rust 复制代码
fn process_message(msg: Message) {
    match msg {
        Message::Quit => println!("收到退出消息"),
        Message::Move { x, y } => println!("移动到坐标:({}, {})", x, y),
        Message::Write(text) => println!("写入内容:{}", text),
        Message::ChangeColor(r, g, b) => println!("修改颜色为 RGB({}, {}, {})", r, g, b),
    }
}

process_message(msg2);  // 输出:移动到坐标:(10, 20)
process_message(msg3);  // 输出:写入内容:hello

常见enum

Option<T>是 Rust 中用于表示 "有值" 或 "无值" 的枚举,彻底避免了空指针(Null)问题。

rust 复制代码
enum Option<T> {
    Some(T),  // 有值:存储类型为T的值
    None,     // 无值
}

Result<T, E>用于表示操作 "成功" 或 "失败" 的结果,是 Rust 错误处理的核心类型。

rust 复制代码
enum Result<T, E> {
    Ok(T),   // 成功:存储类型为T的结果
    Err(E),  // 失败:存储类型为E的错误信息
}

Ordering用于表示两个值的比较结果(小于、等于、大于)

rust 复制代码
enum Ordering {
    Less,    // 小于
    Equal,   // 等于
    Greater, // 大于
}
相关推荐
Source.Liu7 小时前
【Chrono库】WeekdaySet 星期几集合实现解析(weekday_set.rs)
rust·time
是Yu欸7 小时前
Rust 并发实战:从零构建一个内存安全的“番茄时钟”
开发语言·安全·rust
这儿有一堆花8 小时前
用 Rust 复刻 Real Mode 世界
rust
爱吃烤鸡翅的酸菜鱼9 小时前
如何用【rust】做一个命令行版的电子辞典
开发语言·rust
不爱学英文的码字机器9 小时前
Rust 并发实战:使用 Tokio 构建高性能异步 TCP 聊天室
开发语言·tcp/ip·rust
朝九晚五ฺ12 小时前
用Rust从零实现一个迷你Redis服务器
服务器·redis·rust
Amos_Web12 小时前
Rust实战(三):HTTP健康检查引擎 —— 异步Rust与高性能探针
后端·架构·rust
是店小二呀15 小时前
使用Rust构建一个完整的DeepSeekWeb聊天应用
开发语言·后端·rust
是店小二呀1 天前
五分钟理解Rust的核心概念:所有权Rust
开发语言·后端·rust
IT_Beijing_BIT1 天前
Rust入门
开发语言·后端·rust