Rust初学者常犯的十大错误:如何避免它们

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

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

开始课程

引言

Rust 是一种强大的系统编程语言,因其安全性和高性能而日益流行。然而,它的所有权和借用系统常常让初学者感到困惑。在本文中,我们将剖析Rust 初学者的常见错误,帮助您避免这些陷阱,更快地掌握这门语言。我们将探讨借用、生命周期、字符串和内存管理方面的典型问题。



1. 忽略借用检查器规则

最常见的错误是试图同时拥有同一数据的可变引用和不可变引用。Rust 在编译时严格禁止这种操作。



问题:多个引用

fn main() {    let mut data = vec![1, 2, 3];    let ref1 = &data; // 不可变引用    let ref2 = &mut data; // 可变引用 — 错误!    println!("{} {}", ref1[0], ref2[0]);}

编译器会输出错误信息:无法将 `data` 作为可变借用,因为它已被不可变借用。



解决方案:合理的作用域

fn main() {    let mut data = vec![1, 2, 3];    {        let ref1 = &data; // 不可变引用        println!("{}", ref1[0]);    } // ref1 离开作用域    let ref2 = &mut data; // 现在允许了    ref2[0] = 10;    println!("{}", ref2[0]);}

始终关注引用的生命周期。如果需要同时处理可变引用和不可变引用,请将它们放在不同的代码块中。



2. 字符串处理错误:String 与 &str

初学者经常混淆 String(拥有的可变类型)和 &str(字符串切片的引用)。这会导致将字符串传递给函数时出错。



问题:期望所有权而非引用

fn print_length(s: String) {    println!("长度: {}", s.len());}

fn main() { let name = "Alice".to_string(); print_length(name); println!("名字: {}", name); // 错误!name 的所有权已被移动}


解决方案:参数使用 &str

fn print_length(s: &str) {    println!("长度: {}", s.len());}

fn main() { let name = "Alice".to_string(); print_length(&name); // 传递引用 println!("名字: {}", name); // 现在可以正常工作了}

规则:如果函数不需要获取所有权,请使用 &str。这使代码更灵活——您既可以传递 &String,也可以传递像 "text" 这样的字符串字面量。



3. 生命周期错误

当函数返回一个引用时,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 }}

fn main() { let s1 = String::from("short"); let s2 = "long string"; let result = longest(&s1, &s2); println!("最长字符串: {}", result);}

'a 标注告诉编译器,返回的引用不会比输入参数中生命周期最短的那个存活更久。这保证了内存安全。



4. 忽略 Option 和 Result

Rust 中没有空值。相反,它使用 Option<T> 处理值可能缺失的情况,使用 Result<T, E> 进行错误处理。初学者常常在不检查的情况下直接展开 Option。



问题:展开导致崩溃

fn find_user(id: u32) -> Option<String> {    if id == 1 {        Some("Anna".to_string())    }                

博客

书籍推荐