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

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

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

开始课程

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

\n\n

Rust是一种强大且安全的编程语言,但其严格的所有权和借用系统常常让新手感到困惑。在本文中,我们将分析Rust初学者最常遇到的错误。每个错误都附有代码示例、解释和正确的解决方案。让我们开始吧!

\n\n

1. 忽略所有权系统(Ownership)

\n\n

最常见的错误是在值被移动后尝试使用它。在Rust中,每个值只能有一个所有者。

\n\n

❌ 错误代码:

\n
fn main() {\n    let s1 = String::from("你好");\n    let s2 = s1;\n    println!("{}", s1); // 错误!s1不再拥有该字符串\n}\n
\n\n

✅ 正确解决方案:

\n
fn main() {\n    let s1 = String::from("你好");\n    let s2 = s1.clone(); // 显式复制\n    println!("{}", s1); // 现在可以工作\n    println!("{}", s2);\n}\n
\n\n

建议:仅在确实需要时使用.clone()。对于基本类型(i32, bool),复制会自动进行。

\n\n

2. 混淆String和&str

\n\n

新手常常不理解拥有所有权的字符串String和字符串切片&str之间的区别。这会导致在函数间传递字符串时出错。

\n\n

❌ 错误代码:

\n
fn print_message(msg: String) {\n    println!("{}", msg);\n}\n\nfn main() {\n    let greeting = "您好"; // &str\n    print_message(greeting); // 错误!期望String类型\n}\n
\n\n

✅ 正确解决方案:

\n
fn print_message(msg: &str) {\n    println!("{}", msg);\n}\n\nfn main() {\n    let greeting = "您好";\n    print_message(greeting); // 可以工作!\n    \n    let owned = String::from("世界");\n    print_message(&owned); // &String会自动转换为&str\n}\n
\n\n

黄金法则:在函数参数中使用&str,除非你需要传递字符串的所有权。

\n\n

3. 违反借用规则(Borrowing)

\n\n

Rust不允许同时对同一对象拥有可变引用和不可变引用。这可以防止数据竞争。

\n\n

❌ 错误代码:

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

✅ 正确解决方案:

\n
fn main() {\n    let mut data = vec![1, 2, 3];\n    {\n        let ref1 = &data;\n        println!("{}", ref1); // ref1仅在此代码块中存活\n    } // ref1离开作用域\n    let ref2 = &mut data; // 现在可以了\n    ref2.push(4);\n    println!("{:?}", ref2);\n}\n
\n\n

重要提示:引用的作用域在最后一次使用时结束。Rust编译器足够智能来跟踪这一点。

\n\n

4. 生命周期问题(Lifetimes)

\n\n

与生命周期注解相关的错误最让新手害怕。最常见的是返回对局部变量的引用。

\n\n

❌ 错误代码:

\n
fn get_reference() -> &str {\n    let local = String::from("测试");\n    &local // 错误!local在函数退出后将被销毁\n}\n
\n\n

✅ 正确解决方案(通过所有权):

\n
fn get_reference() -> String {\n    let local = String::from("测试");\n    local // 返回所有权\n}\n\nfn main() {\n    let s = get_reference();\n    println!("{}", s);\n}\n
\n\n

✅ 正确解决方案(通过参数):

\n
fn get_reference<'a>(input: &'a str) -> &'a str {\n    input // 返回具有相同生命周期的引用\n}\n\nfn main() {\n    let data = String::from("测试");\n    let result = get_reference(&data);\n    println!("{}", re                

博客

书籍推荐