Rust 入门教程(六):数据结构与集合类型

在前几篇文章中,我们学习了 Rust 的所有权、借用与生命周期,这些是理解 Rust 的核心基础。今天我们来聊聊 Rust 的 常用数据结构与集合类型:字符串、向量(Vec)、哈希表(HashMap)、以及与错误处理密切相关的 OptionResult 枚举。


1. 字符串:String vs &str

Rust 里有两种常见的字符串类型:

  • &str:字符串切片(string slice),是对已有字符串的不可变引用,通常用于字面量("hello")或部分字符串的借用。
  • String:可变、堆分配的字符串类型,支持动态增长和修改。
fn main() {// &str: 字符串切片,不可变let s1: &str = "hello";// String: 可变堆分配字符串let mut s2 = String::from("hello");s2.push_str(", world!"); // 修改字符串println!("s1: {}", s1);println!("s2: {}", s2);// &str -> Stringlet s3 = s1.to_string();// String -> &strlet s4: &str = &s2;
}

🔑 记忆技巧

  • 如果是固定不变的字符串,用 &str
  • 如果需要拼接、修改,用 String

2. Vector:动态数组

Vec<T> 是 Rust 中最常用的集合之一,类似于其他语言的动态数组。

fn main() {// 创建 Vectorlet mut v: Vec<i32> = Vec::new();v.push(10);v.push(20);v.push(30);// 使用宏创建let v2 = vec![1, 2, 3, 4, 5];// 访问元素println!("第一个元素: {}", v[0]);// 使用 get 返回 Option,避免越界match v.get(10) {Some(val) => println!("找到: {}", val),None => println!("索引越界"),}// 遍历for num in &v2 {println!("元素: {}", num);}
}

🔑 要点

  • v[index] 直接访问,可能 panic。
  • v.get(index) 返回 Option,更安全。

3. HashMap:键值对存储

Rust 的 HashMap<K, V> 类似于 Java 的 HashMap 或 Python 的 dict

use std::collections::HashMap;fn main() {let mut scores = HashMap::new();// 插入键值对scores.insert("Alice", 90);scores.insert("Bob", 85);// 访问match scores.get("Alice") {Some(score) => println!("Alice 的分数: {}", score),None => println!("未找到"),}// 覆盖同一个 keyscores.insert("Alice", 95);// 遍历for (name, score) in &scores {println!("{} -> {}", name, score);}// 只在 key 不存在时插入scores.entry("Charlie").or_insert(70);
}

🔑 要点

  • insert 会覆盖已有值。
  • entry().or_insert() 适合做“默认值”插入。

4. Option 与 Result 枚举

4.1 Option:值可能存在,也可能不存在

Rust 没有 null,而是用 Option<T> 表示可选值:

fn find_even(nums: &[i32]) -> Option<i32> {for &num in nums {if num % 2 == 0 {return Some(num);}}None
}fn main() {let nums = vec![1, 3, 5, 8, 11];match find_even(&nums) {Some(n) => println!("找到偶数: {}", n),None => println!("没有偶数"),}
}

4.2 Result:可能成功,也可能失败

Result<T, E> 常用于错误处理:

use std::fs::File;
use std::io::{self, Read};fn read_file(path: &str) -> Result<String, io::Error> {let mut file = File::open(path)?; // ? 语法糖:自动返回错误let mut contents = String::new();file.read_to_string(&mut contents)?;Ok(contents)
}fn main() {match read_file("hello.txt") {Ok(content) => println!("文件内容:\n{}", content),Err(e) => println!("读取失败: {}", e),}
}

5. 模式匹配与解构

Rust 的模式匹配非常强大,常用于解构集合和枚举:

fn main() {let tup = (1, "hello", 3.14);let (x, y, z) = tup;println!("x={}, y={}, z={}", x, y, z);let nums = vec![Some(10), None, Some(20)];for n in nums {match n {Some(val) => println!("找到值 {}", val),None => println!("空"),}}
}

总结

本篇我们学习了 Rust 中最常用的数据结构与集合类型:

  • 字符串String vs &str
  • 集合Vec 动态数组、HashMap 键值对
  • 枚举OptionResult,安全地处理可能缺失或失败的情况
  • 模式匹配:让解构与处理逻辑更加优雅

这些数据结构和枚举,是你在写任何 Rust 应用时都会频繁使用的。下一篇,我们将学习 结构体与枚举的自定义类型,让你能定义更复杂的数据模型 🚀