掌握Rust闭包语法、捕获方式、Fn/FnMut/FnOnce trait,以及闭包的常见应用场景。
fn main() {
// 基本闭包
let add = |a, b| a + b;
println!("3+4={}", add(3, 4));
// 带类型标注
let multiply: fn(i32, i32) -> i32 = |a, b| a * b;
// 多行闭包
let complex = |x| {
let y = x * 2;
let z = y + 1;
z * z
};
// 捕获环境变量
let factor = 3;
let scale = |x| x * factor; // 捕获factor
println!("5*3={}", scale(5));
}
✅ 编译验证通过
fn main() {
// FnOnce — 获取所有权(move)
let name = String::from("Alice");
let greet = move || { // move关键字强制获取所有权
println!("Hello, {}!", name);
};
greet();
// println!("{}", name); // ❌ name已被移入闭包
// FnMut — 可变借用
let mut count = 0;
let mut increment = || {
count += 1; // 可变借用count
count
};
println!("count={}", increment());
println!("count={}", increment());
println!("外部count={}", count); // ✅ FnMut后借用释放
// Fn — 不可变借用
let x = 10;
let read_x = || x; // 不可变借用
println!("x={}", read_x());
println!("x={}", x); // ✅ 仍可用
}
✅ 编译验证通过
| Trait | 捕获方式 | 可调用次数 |
|---|---|---|
FnOnce | 获取所有权 | 一次 |
FnMut | 可变借用 | 多次(需mut) |
Fn | 不可变借用 | 多次 |
关系:Fn ⊂ FnMut ⊂ FnOnce(实现了Fn的也实现了FnMut和FnOnce)
// 闭包作为参数
fn apply<F>(f: F, x: i32) -> i32
where F: Fn(i32) -> i32,
{
f(x)
}
// 闭包作为返回值
fn make_adder(x: i32) -> impl Fn(i32) -> i32 {
move |y| x + y
}
// 或用Box
fn make_multiplier(x: i32) -> Box<dyn Fn(i32) -> i32> {
Box::new(move |y| x * y)
}
fn main() {
let add5 = make_adder(5);
println!("5+3={}", add5(3));
let mul3 = make_multiplier(3);
println!("3*4={}", mul3(4));
}
✅ 编译验证通过
fn main() {
// 缓存/记忆化
use std::collections::HashMap;
let mut cache: HashMap<i32, i32> = HashMap::new();
let mut expensive = |n| {
*cache.entry(n).or_insert_with(|| {
println!("计算中...");
n * n
})
};
println!("{}", expensive(5)); // 计算
println!("{}", expensive(5)); // 缓存命中!
// 排序自定义键
let mut people = vec![("Alice", 30), ("Bob", 25), ("Charlie", 35)];
people.sort_by_key(|p| p.1); // 按年龄排序
// 条件过滤
let threshold = 28;
let older: Vec<_> = people.iter()
.filter(|p| p.1 > threshold)
.collect();
}
✅ 编译验证通过
实现一个柯里化函数:add(a)(b) = a + b。
用闭包实现一个简单的事件系统,支持注册和触发。
实现一个Lazy<T>类型,只在第一次访问时计算值。
掌握闭包——Rust函数式编程的核心
以下资源帮助你深入学习本课主题:
本课涉及的核心概念,确保你理解每一个:
| 术语 | 说明 |
|---|---|
| 所有权 | Rust内存管理的核心机制,每个值有唯一所有者 |
| 借用 | 通过引用访问数据,不获取所有权 |
| 生命周期 | 引用有效的范围,编译期分析工具 |
| trait | Rust的接口/抽象机制,类似其他语言的接口 |
| 泛型 | 参数化类型,零成本抽象 |
| 模式匹配 | 强大的数据解构和分支机制 |
| 零成本抽象 | 高层抽象不引入运行时开销 |
| fearless concurrency | 编译器保证线程安全 |
Q: Rust学习曲线真的很陡吗?
A: 前期确实需要适应所有权和借用检查器,但一旦理解了,这些概念会让你的代码更可靠。大多数人2-4周就能上手。
Q: Rust适合什么项目?
A: 系统编程、Web服务、CLI工具、嵌入式、WASM、网络服务、数据库等。基本上需要性能和安全的地方都适合。
Q: 遇到编译错误怎么办?
A: Rust编译器的错误信息非常友好!仔细阅读,通常会指出问题所在和修复建议。也可以用cargo clippy获取更多提示。