Rust 入门教程(六):数据结构与集合类型
在前几篇文章中,我们学习了 Rust 的所有权、借用与生命周期,这些是理解 Rust 的核心基础。今天我们来聊聊 Rust 的 常用数据结构与集合类型:字符串、向量(Vec
)、哈希表(HashMap
)、以及与错误处理密切相关的 Option
和 Result
枚举。
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
键值对 - 枚举:
Option
与Result
,安全地处理可能缺失或失败的情况 - 模式匹配:让解构与处理逻辑更加优雅
这些数据结构和枚举,是你在写任何 Rust 应用时都会频繁使用的。下一篇,我们将学习 结构体与枚举的自定义类型,让你能定义更复杂的数据模型 🚀