下面我将以零基础教学的视角,逐一讲述 Rust 标准库 std 中最常用、最核心的模块和类型。每一节我会说明:它是什么、为什么需要、怎么用、有哪些关键方法和常见例子,并尽量结合之前冒险者程序中的代码。
1. 预导入(Prelude)—— 自动给你准备的工具箱
在 Rust 里,每个程序都会自动导入一些最基本的东西,不需要你写 use std::...。它们包括:
Option::Some、Option::NoneResult::Ok、Result::ErrVec、String、Boxprintln!、format!宏Clone、Copy、Drop等基础 trait
理解方式: 就像一盒你买来就能直接用的基础文具(铅笔、橡皮、尺子),不需要再专门申请。因此初学者最先接触的 Option、Result、Vec 等,都是预导入的,可以直接使用。
2. Option—— 可能没有值的“盒子”
Option 是一个枚举,代表一个值可能存在,也可能不存在。
enum Option<T> {Some(T), // 有值None, // 没有值
}
为什么需要? 在很多语言里,null 或 None 常常导致崩溃。Rust 用 Option 强制你处理“没有值”的情况,从而避免空指针异常。
常用方法:
unwrap():如果有值就拿出来,没有值就崩溃(不要随意使用)。expect("信息"):类似unwrap,但可以自定义错误信息。is_some()/is_none():判断是否有值。match或if let:安全地取出值。
教学代码例子:
let secret = Some("宝藏"); // secret 是 Option<&str>,里面有 "宝藏"
match secret {Some(msg) => println!("{}", msg),None => println!("啥也没有"),
}
3. Result—— 操作可能失败
Result 也是枚举,专用于可能出错的操作。
enum Result<T, E> {Ok(T), // 成功,带着结果 TErr(E), // 失败,带着错误信息 E
}
为什么需要? 打开文件、网络连接、读取输入等都可能失败。Result 让你必须处理错误,否则编译不通过。
常用方法:
unwrap()/expect():成功拿值,失败则崩溃。?运算符:如果成功就继续,失败就立刻把错误返回给上级函数。is_ok()/is_err():判断是否成功。
教学代码例子:
fn use_item(&mut self, index: usize) -> Result<Item, GameError> {if index >= self.inventory.len() {return Err(GameError::NoItem); // 返回错误}Ok(self.inventory.remove(index)) // 返回成功
}// 调用处用 match 处理
match hero.use_item(0) {Ok(item) => log!("使用物品: {}", item),Err(e) => log!("错误: {}", e),
}
4. String 和 &str—— 存放文字的两种形式
&str(字符串切片):对一段 UTF-8 文本的“借用引用”,不能修改,通常是"hello"这种字面量。String:拥有所有权的、可增长的字符串,可以修改和添加内容。
关键区别: &str 便宜、轻量,但无权修改;String 是独立的,可以随意增删改。
常用转换和方法:
"hello".to_string()或String::from("hello"):字面量变 String。push_str(" world"):追加切片。push('!'):追加单个字符。len():获取字节长度(UTF-8 下要注意中文多字节)。as_str():得到&str。
教学代码中:
let name: &str = "千字文"; // 切片,借用
let s = "卷轴".to_string(); // String,拥有所有权
book_bag.add(s); // s 被移动进背包
5. Vec—— 动态数组
Vec<T> 是存放很多相同类型元素的列表,可自动增长。
创建和操作:
Vec::new():空向量。vec![1,2,3]:宏快速创建。.push(元素):在末尾加入。.pop():移除末尾并返回Option。.len():获取元素个数。.get(index):安全索引,返回Option<&T>。- 直接
v[0]索引会崩溃,推荐用get。
教学代码中:
let mut inventory: Vec<Item> = Vec::new();
inventory.push(Item::Sword(30));
// 迭代
for item in &inventory { ... }
6. 格式化:fmt 和 Display / Debug
std::fmt 模块提供了如何把各种类型变成字符串打印出来的 trait:
Debug:用于调试,用{:?}打印,几乎所有标准类型都实现了,也可用#[derive(Debug)]自动生成。Display:用于用户友好的展示,用{}打印,需要手动实现。
教学代码中我们实现了 Display:
impl fmt::Display for Item {fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {match self {Item::Sword(atk) => write!(f, "剑(攻{})", atk),...}}
}
这样 println!("{}", item) 就会输出友好的文字。
7. Clone 与 Copy—— 如何复制值
Copy:轻量拷贝,比如整数、布尔,赋值时自动复制,原变量仍可使用。无法手动实现Copy的类型不能添加。Clone:显式复制,调用.clone(),适用于字符串、Vec 等复杂类型,会有性能开销。
教学意义: 初学者常困惑于所有权转移,Copy 类型不需要担心;非 Copy 类型要用 clone() 来深复制,如 s1.clone()。
8. HashMap—— 键值对字典
std::collections::HashMap<K, V> 通过键快速查找值。
常用方法:
HashMap::new()创建。.insert(key, value)插入。.get(&key)返回Option<&V>。.entry(key).or_insert(value)如果有键就返回其值,没有就插入并提供可变引用。
代码例子(未在教学代码中,但典型):
use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert("Blue", 10);
let team_score = scores.get("Blue").unwrap_or(&0);
9. 智能指针:Box, Rc, Arc, RefCell
这些都是帮助管理内存和所有权的高级工具,但在零基础教学中先建立印象即可。
Box<T>:把数据放在堆上,比如解决递归类型的尺寸问题。简单理解:一个指向堆内存的指针,拥有数据。Rc<T>:单线程引用计数,允许多个所有者共享数据,不可变引用。用Rc::clone(&rc)增加引用。RefCell<T>:内部可变性,允许在只拥有不可变引用时修改内部值,但规则由编译时检查移到运行时,违规会 panic。Arc<T>:线程安全的Rc,用于多线程共享。Mutex<T>:互斥锁,配合Arc可以安全地在多线程中修改同一份数据。
教学代码中:
// Rc + RefCell 让多个指针共享一个可变冒险者
let adv = Rc::new(RefCell::new(Adventurer::new("共享者")));
let adv2 = Rc::clone(&adv);
adv2.borrow_mut().health -= 10; // 修改内部
10. 输入输出:io 模块
std::io 提供了 Read 和 Write trait,以及标准输入 stdin()、标准输出 stdout()。
最常用的是防止窗口闪退:
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap(); // 等待用户输入回车
另外也包含 File 的读取,但 File 属于 std::fs,io 提供 Read trait。
11. 文件系统:fs 模块
std::fs 处理文件和目录。
常用:
File::open("路径"):打开文件,返回Result<File>。read_to_string("路径"):一次性读取为字符串。write("路径", 内容):写入文件。create_dir("目录")等。
教学代码中:
let mut file = File::open("adventure.toml")?;
let mut content = String::new();
file.read_to_string(&mut content)?;
12. 线程与同步:thread, Arc, Mutex, mpsc
std::thread::spawn(闭包):创建新线程。move闭包:强制移动所有权进线程。handle.join().unwrap():等待线程结束。Arc<Mutex<T>>:多线程共享可变数据。
教学代码:
let team = Arc::new(Mutex::new(vec![]));
let team2 = Arc::clone(&team);
thread::spawn(move || {team2.lock().unwrap().push("战友A".to_string());
}).join().unwrap();
13. 迭代器:iter 模块与 Iterator trait
迭代器是对数据序列进行操作的强大工具,来自 std::iter。
核心方法:
.iter()/.iter_mut()/.into_iter()获取迭代器。.map(|x| ...)转换每个元素。.filter(|x| ...)保留符合条件的元素。.collect()把迭代器变回集合。.sum(),.count(),.find()等消费者方法。
教学代码:
let strong: Vec<_> = items.iter().filter(|it| matches!(it, Item::Sword(a) if *a > 5)).collect();
14. 错误处理 trait:Error
std::error::Error 是所有错误类型的公共 trait,通常配合 Box<dyn Error> 使用,表示任意类型的错误。自定义错误只要实现了 Display 和 Debug,再 impl Error for MyError {} 即可。
教学代码:
fn load_config(path: &str) -> Result<String, Box<dyn Error>> { ... }
15. 其他常用模块速览
std::env:获取环境变量、命令行参数args()。std::process:运行外部命令,退出程序exit()。std::time:Duration(时长)、Instant(时间点)。std::cmp:Ordering枚举(Less, Equal, Greater),max/min函数。std::char:判断字符类型的方法。std::mem:内存操作,如swap,size_of。
教学建议
对于零基础学习者,建议按照以下顺序逐步掌握:
Option、Result、String/&str、Vec(最常用)fmt::Display/Debug、Clone/Copy(打印与复制)HashMap(当需要字典时)Box、Rc、RefCell(理解所有权进阶)thread、Arc、Mutex(并发入门)fs、io(文件操作)- 迭代器方法链(
map/filter/collect等)
每学一个,都可以在冒险者程序里找到对应示例,通过阅读注释 + 运行程序 + 动手修改的方式,逐步把 Rust 的标准库用起来。
