相关推荐recommended
Rust|60个新手常犯的错误
作者:mmseoamin日期:2024-04-30

1.错误地使用可变和不可变借用

let mut data = vec![1, 2, 3];
let x = &data[0];
data.push(4);
println!("{}", x);

不能在有不可变引用时修改数据。

2.忘记处理 Option

fn main() {
    let some_number = Some(5);
    let sum = some_number + 5; // 错误:Option 类型不能这样直接使用
}

使用 match 或 if let 来处理 Option。

let sum = if let Some(n) = some_number { n + 5 } else { 0 };

3.期望的引用而不是实际值

fn foo(x: &i32) {
    // ...
}
fn main() {
    let x = 10;
    foo(x); // 错误:应传递引用而不是值
}

传递引用而不是值。

foo(&x);

4.不匹配的类型

fn main() {
    let flag = true;
    let number = if flag { 5 } else { "six" }; // 错误:不匹配的类型
}

解决方案:确保所有的分支返回相同的类型。

let number = if flag { 5 } else { 6 };

5.忘记导入trait

use std::io::Write; // 因为 Write trait 已导入
fn main() {
    let mut buffer = Vec::new();
    buffer.write_all(b"hello").unwrap();
    // 现在可以正常使用 write_all 方法,因为 Write trait 已导入
}

必须导入Write trait才能使用其方法。

6.试图在遍历向量的同时修改它

fn main() {
    let mut vec = vec![1, 2, 3];
    for val in &vec {
        vec.push(*val + 10); // 错误!不能在遍历时修改vec
    }
}

修复: 使用迭代器的.for_each()方法或者先收集需要做的更改,然后再应用它们。

7.不使用可变引用来修改向量中的值

fn main() {
    let mut vec = vec![1, 2, 3];
    for val in vec.iter() {
        *val *= 2; // 错误!因为`val`是不可变引用
    }
}

修复: 使用.iter_mut()来获取可变引用。

for val in vec.iter_mut() {
    *val *= 2;
}

8.在向量迭代时错误地使用索引

fn main() {
    let vec = vec![10, 20, 30];
    for i in 0..vec.len() {
        println!("{}", vec[i]); // 索引方式正确
        // 如果修改为 vec[i+1] 就会出错
    }
}

修复: 确保在使用索引时不要越界。

9.未处理get()返回Option的情况

fn main() {
    let vec = vec![1, 2, 3];
    let val = vec.get(5); // 返回None,因为索引超出范围
    println!("{}", val.unwrap()); // 错误!这会panic
}

修复: 使用.unwrap_or()或.unwrap_or_else()处理None情况。

let val = vec.get(5).unwrap_or(&0); // 使用默认值
println!("{}", val);

10.使用不恰当的迭代器消费方法

fn main() {
    let vec = vec![1, 2, 3, 4, 5];
    let even_numbers: Vec<_> = vec.iter().map(|x| x * 2).collect(); // 正确
    let even_number = even_numbers.first().unwrap(); // 尝试获取第一个数
    println!("{}", even_number * 2); // 错误!even_number的类型是&&i32
}

修复: 在使用值之前进行适当的解引用。

println!("{}", (**even_number) * 2); // 解引用两次到i32

11.在遍历过程中错误地使用for循环去显式创建迭代器

fn main() {
    let vec = vec![1, 2, 3];
    for i in 0..vec.iter().count() { // 错误!不必要的计数和索引
        println!("{}", vec[i]);
    }
}

修复: 直接遍历迭代器。

for &val in vec.iter() {
    println!("{}", val);
}

12.忘记引用计数(Rc/Arc)中的借用规则

use std::rc::Rc;
let foo = Rc::new(5);
let a = *foo;

13.使用*foo应该先调用.clone()去获取Rc里面的值

错误地对字符串切片

let s = String::from("hello");
let part = &s[0..2];

字符串索引应该在字符边界处切片。使用.chars()和.bytes()

14.未处理泛型边界

fn print_it(value: T) {
    println!("{}", value);
}

需要为T添加Display trait约束。

15.尝试修改迭代器产生的不可变引用

let mut vector = vec![1, 2, 3];
for item in vector.iter_mut() {
    *item += 10;
}

使用iter_mut()来获取可变引用。

16.没有正确使用借用和所有权