Rust初学者十大常见错误及如何避免

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

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

开始课程

引言:为什么 Rust 看起来很难?

Rust 是一种现代系统编程语言,它能在没有垃圾收集器的情况下保证内存安全。然而,其严格的类型系统和独特的所有权模型常常让初学者感到困惑。如果你刚开始学习 Rust,并且不断看到编译器报出的红色错误信息,请不要气馁——这很正常。在本文中,我们将剖析 Rust 初学者最常犯的 10 个错误,并展示如何修复它们。



1. 忽略借用检查器

最常见的错误是在移动(move)后尝试使用某个值,或者创建了可变引用。Rust 编译器(借用检查器)严格执行所有权规则。



问题

let s1 = String::from("hello");let s2 = s1; // s1 移动到了 s2println!("{}", s1); // 错误!s1 不再拥有该数据


解决方案

如果你需要复制数据,请使用 clone(),或者传递引用 &:

let s1 = String::from("hello");let s2 = &s1; // 借用println!("{} and {}", s1, s2); // 有效!


提示: 如果编译器报错说所有权问题——你很可能需要的是一个引用,而不是完全移动。



2. 混淆 String 和 &str

初学者常常不理解拥有所有权的类型 String 和切片 &str 之间的区别。这会导致类型错误和不必要的内存分配。



问题

fn greet(name: &str) {    println!("Hello, {}!", name);}

let my_name = String::from("Anna");greet(my_name); // 错误:期望 &str,但得到 String


解决方案

传递一个指向 String 的引用——它会自动强制转换为 &str:

greet(&my_name); // 有效,得益于 Deref 强制转换


对于拥有和修改字符串,使用 String;对于读取和传递给函数,使用 &str。



3. 过度使用 unwrap() 和 expect()

unwrap() 和 expect() 方法是处理 Option 或 Result 的快捷方式,但它们在出错时会导致程序恐慌(panic)。这在生产代码中是不可接受的。



问题

let number: Option<i32> = None;let value = number.unwrap(); // 程序恐慌!


解决方案

使用 match 或者 unwrap_or、unwrap_or_else 等方法:

let value = number.unwrap_or(0); // 如果是 None,返回 0// 或者使用 matchmatch number {    Some(v) => println!("{}", v),    None => println!("值不存在"),}


对于 Result,使用 ? 操作符将错误向上传播。



4. 错误地使用可变引用

“一个可变引用 或 多个不可变引用”这条规则经常被违反。



问题

let mut data = vec![1, 2, 3];let ref1 = &mut data;let ref2 = &mut data; // 错误!println!("{}", ref1);


解决方案

使用花括号限制可变引用的作用域:

let mut data = vec![1, 2, 3];{    let ref1 = &mut data;    ref1.push(4);} // ref1 离开作用域let ref2 = &mut data; // 现在可以了ref2.push(5);


5. 忘记生命周期

当编译器要求显式指定生命周期时,初学者常常卡住。最常见的错误是返回对局部变量的引用。



问题

fn get_ref() -> &str {    let s = String::from("test");    &s // 错误:返回对局部变量的引用}


解决方案

要么返回拥有所有权的类型 String,要么接受一个引用作为参数:



                
                

博客

书籍推荐