闭包只是定义了代码,存储代码,并不是执行,切记。
Rust的闭包类型分为三种:
1.Fn
2.FnMut
3.FnOnce
不同之处:
1.它们的调用方法分别采用&self、&mut self和self,这意味着Fn对其捕获具有不可变的访问权限,FnMut获得可变的访问权限,FnOnce可以获得所有权。
2.Fn和FnMut类型的闭包可以执行多次,而FnOnce类型的闭包只能执行一次。
move关键字:
1.如果没有实现Copy,就是move语义,会发生移动。
2.如果实现Copy,则是copy语义,会发生拷贝。
值得注意的是move与闭包的类型没有关系
示例代码:
1.Fn
#[derive(Debug)]
struct Person {
age: usize,
}
impl Person {
fn print(self) {
println!("{:?}", self);
}
fn print_ref(&self) {
println!("{:?}", self);
}
fn print_mut_ref(&mut self) {
println!("{:?}", self);
}
}
fn call_fn<F: Fn()>(f: F) {
f();
}
fn main() {
let mut person = Person { age: 18 };
call_fn(|| {
// Fn 可以获得不可变的访问权限
person.print_ref();
// Fn 不可以获得可变的访问权限
// person.print_mut_ref();
// Fn 不可以获得所有权
// person.print();
});
}
2.FnMut
#[derive(Debug)]
struct Person {
age: usize,
}
impl Person {
fn print(self) {
println!("{:?}", self);
}
fn print_ref(&self) {
println!("{:?}", self);
}
fn print_mut_ref(&mut self) {
println!("{:?}", self);
}
}
fn call_fn_mut<F: FnMut()>(mut f: F) {
f();
}
fn main() {
let mut person = Person { age: 18 };
call_fn_mut(|| {
// FnMut 可以获得不可变的访问权限
person.print_ref();
// FnMut 可以获得可变的访问权限
person.print_mut_ref();
// FnMut 不可以获得所有权
// person.print();
});
}
3.FnOnce
#[derive(Debug)]
struct Person {
age: usize,
}
impl Person {
fn print(self) {
println!("{:?}", self);
}
fn print_ref(&self) {
println!("{:?}", self);
}
fn print_mut_ref(&mut self) {
println!("{:?}", self);
}
}
fn call_fn_once<F: FnOnce()>(f: F) {
f();
}
fn main() {
let mut person = Person { age: 18 };
call_fn_once(|| {
// FnOnce 可以获得不可变的访问权限
person.print_ref();
// FnOnce 可以获得可变的访问权限
person.print_mut_ref();
// FnOnce 可以获得所有权
person.print();
});
}
4.Fn/FnMut/FnOnce
fn call_fn_once<F>(f: F, s: String)
where F: FnOnce(String) -> String
{
let res = f(s);
println!("res: {}", res);
}
fn call_fn_mut<F>(mut f: F, s: String)
where F: FnMut(String) -> String
{
let res = f(s);
println!("res: {}", res);
}
fn call_fn<F>(f: F, s: String)
where F: Fn(String) -> String
{
let res = f(s);
println!("res: {}", res);
}
fn main() {
let name1 = "upfly".to_owned();
let mut name2 = name1.clone();
let name3 = name1.clone();
// Fn
let c1 = |s: String| -> String {
println!("name1: {}", name1);
s
};
// FnMut
let c2 = |s: String| -> String {
name2.push_str("666");
println!("name2: {}", name2);
s
};
// FnOnce
let c3 = move |s: String| -> String {
println!("name3: {}", name3);
let _name: String = name3;
s
};
// FnOnce 可以接受 Fn/FnMut/FnOnce
// Ok
// call_fn_once(c1, "fn_once fn".to_owned());
// Ok
// call_fn_once(c2, "fn_once fn_mut".to_owned());
// Ok
// call_fn_once(c3, "fn_once fn_once".to_owned());
// FnMut 只能接受 Fn 和 FnMut
// Ok
// call_fn_mut(c1, "fn_mut fn".to_owned());
// Ok
// call_fn_mut(c2, "fn_mut fn_mut".to_owned());
// Err
// call_fn_mut(c3, "fn_mut fn_once".to_owned());
// Fn 只能接受 Fn
// Ok
// call_fn(c1, "fn fn".to_owned());
// Err
// call_fn(c2, "fn fn_mut".to_owned());
// Err
// call_fn(c3, "fn fn_once".to_owned());
}
5.move
#[derive(Debug, Clone, Copy)]
struct Person {
age: usize,
}
fn call_fn<F: Fn()>(f: F) {
f();
}
fn main() {
let person = Person { age: 18 };
call_fn(move || {
println!("{:?}", person);
});
// 不实现 Copy,报错 value borrowed here after move
println!("{:?}", person);
}