面试题答案
一键面试struct MyStruct {
data: Vec<i32>,
}
fn process_struct(s: MyStruct) -> i32 {
match s.data.len() {
0 => 0,
1 => *s.data.first().unwrap(),
_ => s.data.iter().sum(),
}
}
解构访问结构体字段
在match
表达式中,通常可以这样解构结构体:
struct Point {
x: i32,
y: i32,
}
fn print_point(p: Point) {
match p {
Point { x, y } => println!("x: {}, y: {}", x, y),
}
}
对于我们题目中的MyStruct
,如果要在match
表达式中直接解构访问data
字段,可以这样写:
fn process_struct_alt(s: MyStruct) -> i32 {
match s {
MyStruct { data } => match data.len() {
0 => 0,
1 => *data.first().unwrap(),
_ => data.iter().sum(),
},
}
}
处理借用问题
- 值捕获:在上面的
process_struct
函数中,s
是按值传递进来的,所以match
表达式可以直接消耗MyStruct
实例。在每个分支中,data
也是按值获取,不存在借用问题。 - 借用捕获:如果函数接收的是结构体的引用
&MyStruct
,例如:
fn process_struct_ref(s: &MyStruct) -> i32 {
match s.data.len() {
0 => 0,
1 => *s.data.first().unwrap(),
_ => s.data.iter().sum(),
}
}
这里match
表达式处理的是&MyStruct
,在分支中data
也是借用的。因为iter
方法返回的迭代器也只是借用data
中的元素,所以sum
方法可以正确工作。在这种情况下,要注意生命周期问题,确保借用的生命周期符合Rust的规则。例如,不能在match
分支中返回一个指向data
内部元素的引用,因为该引用的生命周期会比&MyStruct
的生命周期短,会导致悬空引用。