Rust初学者常见错误大全:从A到Z

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么Rust看似困难,但值得学习

Rust是一种承诺无需垃圾回收器即可安全管理内存并提供高性能的语言。然而,正是这些优势成为了初学者的绊脚石。Rust编译器在细节上极其严格:它不允许未定义行为、悬垂指针或数据竞争。在本文中,我们将分析Rust初学者最常见的错误——从最频繁到最隐蔽的。您将学习如何避免这些错误,并加速掌握这门语言。



1. 与借用检查器(Borrow Checker)的斗争

初学者最著名的"痛点"是所有权(ownership)和借用(borrowing)系统。如果数据可能被修改或删除,编译器不允许您随意创建对数据的引用。



1.1. 尝试通过不可变引用修改数据

最初的错误之一——尝试修改一个已有不可变引用(&)的变量。

let mut x = 5;let y = &x;   // 不可变引用let z = &mut x; // 错误:存在不可变引用时,不能创建可变引用println!("{}", y);

如何修复:确保在创建可变引用之前,不可变引用的作用域已经结束。使用花括号限制作用域。

let mut x = 5;{    let y = &x;   // y的作用域被限制    println!("{}", y);}let z = &mut x;   // 现在可以了


1.2. 返回对局部变量的引用

初学者经常尝试返回对函数内部创建的数据的引用。这会导致"悬垂引用"(dangling reference)错误。

fn get_ref() -> &String {    let s = String::from("hello");    &s // 错误:s在函数退出后将被删除}

如何修复:返回所有权(字符串本身),或者如果数据永久存在,则使用静态生命周期('static)。

fn get_string() -> String {    let s = String::from("hello");    s // 转移所有权}


2. 生命周期(lifetimes)的错误使用

当您开始使用接受多个引用的函数时,编译器要求指定它们之间的生命周期关系。初学者要么忽略生命周期,要么在不必要的地方到处写'static。



2.1. 在函数签名中省略生命周期注解

如果函数接受两个引用并返回一个,Rust无法自行确定哪个引用"存活"得更久。

fn longest(x: &str, y: &str) -> &str { // 错误:需要生命周期    if x.len() > y.len() { x } else { y }}

如何修复:添加一个通用的生命周期参数。

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {    if x.len() > y.len() { x } else { y }}


2.2. 过度使用'static

'static 意味着引用在整个程序运行期间存在。将其用于字符串字面量是可以的,但对于动态数据来说是不好的实践。

fn get_static() -> &'static str {    "hello" // 正确}

fn get_dynamic() -> &'static str { let s = String::from("hello"); &s // 错误:s不会永久存在}

建议:尽量避免不必要地使用'static。最好转移所有权,或者在多线程场景中使用Arc<Mutex<T>>。



3. 滥用unwrap()和panic

Rust鼓励通过Result和Option进行显式错误处理。但初学者经常到处使用.unwrap()或.expect()来"堵住"编译器。这会导致运行时panic。



3.1. 忽略Option和Result

博客

书籍推荐