引言:为什么Rust在面试中要求如此之高?
Rust是一种以内存安全和高性能著称的系统编程语言。Rust编译器严格但公正:它不允许所有权错误或悬垂引用。这就是为什么在Rust面试中,很少照本宣科地问语法。相反,面试官会测试对内存模型、资源管理和惯用代码的深入理解。
在本文中,我们将剖析面向初级和中级Rust开发人员面试中最常被问到的十大问题。每个问题都附带解释和代码示例。如果你正在准备面试,这篇文章将成为你的检查清单。
1. 所有权与借用
这是Rust的基础。不理解所有权,你就无法通过面试。面试官可能会要求你解释String和&str的区别,或者询问为什么某些代码无法编译。
问题:解释什么是所有权,以及数据在函数中是如何传递的。
回答:在Rust中,每个值都有且只有一个所有者。当一个变量离开作用域时,该值会被丢弃。将值传递给函数意味着所有权的移动,除非该类型实现了Copy trait。
fn main() { let s1 = String::from("hello"); let s2 = s1; // s1的所有权被移动到s2 // println!("{}", s1); // 错误!s1不再拥有该字符串 println!("{}", s2);}如果你想传递数据而不丢失所有权,可以使用引用(&):
fn main() { let s1 = String::from("hello"); let len = calculate_length(&s1); // 借用 println!("字符串 '{}' 的长度是 {}。", s1, len);}
fn calculate_length(s: &String) -> usize { s.len()}问题:什么是可变借用,为什么只能有一个?
回答:可变借用(&mut)允许你通过引用更改值。编译器保证在作用域内只有一个可变引用,以防止数据竞争。
fn main() { let mut s = String::from("hello"); let r1 = &mut s; // let r2 = &mut s; // 错误!不能同时拥有两个可变引用 r1.push_str(", world"); println!("{}", r1);}2. 生命周期
生命周期是让初学者感到害怕的地方。在面试中,你会被要求解释为什么需要'a注解,以及编译器是如何推断生命周期的。
问题:什么时候需要显式指定生命周期?
回答:当函数返回一个引用,并且编译器无法自行确定该引用能存活多久时。一个典型的例子是返回两个字符串中较长者的函数:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y }}
fn main() { let string1 = String::from("long string"); let result; { let string2 = String::from("short"); result = longest(&string1, &string2); } // println!("{}", result); // 错误!string2已被丢弃,引用成为悬垂引用}注解'a的意思是:"返回引用的生命周期等于输入引用中较短的那个生命周期。"
问题:什么是生命周期省略(生命周期省略规则)?
回答:在简单情况下,编译器会自动插入生命周期注解。如果一个函数接受一个引用并返回一个引用,生命周期会被推断出来。如果有多个输入引用,就需要显式地指定生命周期。
3. 枚举、模式匹配与Option/Result
Rust广泛使用代数类型。