第四章:结构体与枚举 —— 数据的“骨架”

Unknown Author 独酌
2025-11-19 Rust, Book

在前端开发中,我们每天都在和 Object(对象)打交道。

1
2
3
4
5
6
7
8
// TypeScript
interface User {
username: string;
email: string;
active: boolean;
}

const user = { username: "Gemini", email: "ai@google.com", active: true };

在 Rust 中,这叫 Struct (结构体)。

1. Struct:更严格的对象

语法几乎一模一样,只是把 interface 换成了 struct,把 const 换成了 let

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct User {
username: String,
email: String,
active: bool, // Rust 的布尔值叫 bool
}

fn main() {
// 实例化 Struct
let user1 = User {
username: String::from("Gemini"),
email: String::from("ai@google.com"),
active: true,
};

println!("User: {}", user1.username);
}

最大的区别: 在 JS 里,你可以随时给对象追加属性 (user.isAdmin = true)。 在 Rust 里,不行。Struct 的形状在定义时就锁死了,既不能多,也不能少。

2. Enum:Rust 的“杀手锏”

这是本章的重头戏。

在 TypeScript 中,枚举 (Enum) 通常只是一组常量数字或字符串的映射:

1
2
3
4
5
6
7
// TypeScript
enum Status {
Pending,
Success,
Failed
}
// 很难携带额外数据,除非你再定义一堆 Interface 配合 Union Types

但在 Rust 中,枚举可以携带数据! 这让它变得极其强大,特别适合用来描述 “状态” 或者 “事件”

想象一下你在写一个 Redux reducer,你有不同的 Action。有的 Action 不需要参数,有的需要字符串,有的需要对象。

在 Rust 里,我们可以把它们统统塞进一个 Enum:

1
2
3
4
5
6
7
8
9
10
11
12
13
enum WebEvent {
// 1. 没有任何数据的单元 (像 TS 的 Enum)
PageLoad,

// 2. 包含一个 String 的变体
PageUnload(String),

// 3. 包含两个数字的变体 (比如坐标)
KeyPress(char),

// 4. 甚至可以包含像 Struct 一样的命名数据
Click { x: i64, y: i64 },
}

看懂了吗?PageLoad 只是个信号;但 Click 里面竟然直接打包了 xy 坐标数据!
这意味着一个 WebEvent 类型的变量,可能是个简单的 PageLoad,也可能是个复杂的 Click 对象。这在处理复杂业务逻辑时非常优雅。

🧠 随堂小测验

我们将 Struct 和 Enum 结合起来做一个小练习。

假设我们在做一个 “消息通知系统”。 我们需要定义一个枚举 Message,它有两种可能的情况:

  1. Quit:退出(没有关联数据)。
  2. Write:写入消息(关联一个 String 字符串)。

请根据上面的 WebEvent 例子,把下面的代码补充完整:

1
2
3
4
5
6
7
8
9
enum Message {
Quit,
// 👇 请在这里补充 Write 变体,让它能携带一个 String
___________
}

fn main() {
let msg = Message::Write(String::from("Hello Rust"));
}

请写出空白处应该填入的代码。

答案

🥳 Write(String)

这种写法叫做 Tuple Variant (元组变体)。你就像给这个枚举贴了个标签,顺便塞进去了一个数据包。

独酌

独酌

小镇码农

相关文章