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<T>(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.没有正确使用借用和所有权