闭包
Rust 的闭包 (closure) 是匿名函数,可以将其保存在变量中或作为参数传递给其他函数。
fn main() {
let closure = |x| x*x;
assert_eq!(closure(3),9);
}
虽然闭包没有标注变量类型,编译器会根据使用的类型推断,使用不同的类型不会编译通过。
闭包可以通过三种方式获取环境中的值:
- 不可变借用
- 可变借用
- 获取所有权
fn main() {
// 1. 不可变借用
let data = "不变数据".to_string();
let immutably_borrow = || println!("data: {data}");
println!("不可变借用:");
immutably_borrow();
// 2. 可变借用
let mut mut_data = "可变数据".to_string();
let mut mut_borrow = || {mut_data.push('+');println!("data: {mut_data}");};
// 在使用可变借用前,不能再使用不变借用,取消下一行注释会报错:cannot borrow `mut_data` as immutable because it is also borrowed as mutable
// println!("data: {mut_data}");
println!("可变借用:");
mut_borrow();
}
Move
资源同时只能有一个所有者,资源的所有权转移后,前所有者将不能再被使用,防止出现悬空指针(Dangling Pointer)。
move
的作用是按值捕获闭包的环境,move
将通过引用或可变引用捕获的任何变量转换为按值捕获的变量。
例子:
fn main() {
let data = vec![1, 2, 3];
// 不会打印
let closure = move || println!("捕获 {data:?}");
// data 将不可用,不注释下行会出现编译错误:value borrowed here after move
// println!("print {data:?}");
// 在这里打印
println!("指示位置用 ↓");
closure();
}
注意:move
闭包仍然可以实现 Fn
或 FnMut
,即使它们通过 move
捕获变量。这是因为闭包类型实现的特征取决于闭包对捕获值的作用,而不是它如何捕获它们:
Fn 特性
待续