| name | rust-anti-pattern |
| description | Rust 反模式与常见错误。处理代码审查、clone、unwrap、String 用法、迭代器等问题。触发词:anti-pattern, common mistake, clone, unwrap, code review, 代码异味, 常见错误, 代码审查, refactor, 重构 |
| globs | ["**/*.rs"] |
Rust 反模式与常见错误
核心问题
这个模式是否掩盖了设计问题?
代码能跑不代表代码好。反模式是"能用但不该用"的模式。
Top 5 新手常犯错误
| 排名 | 错误 | 正确做法 |
|---|
| 1 | 用 .clone() 躲避借用检查 | 使用引用 |
| 2 | 生产代码用 .unwrap() | 用 ? 或 with_context() |
| 3 | 什么都是 String | 用 &str,必要时用 Cow<str> |
| 4 | 索引循环 | 用迭代器 .iter(), .enumerate() |
| 5 | 与生命周期对抗 | 重新设计数据结构 |
常见反模式
反模式 1:到处 clone
fn process(user: User) {
let name = user.name.clone();
}
fn process(user: &User) {
let name = &user.name;
}
什么时候真的需要 clone:
- 确实需要独立副本
- API 设计需要 owned 值
- 数据流向需要
反模式 2:生产代码用 unwrap
let config = File::open("config.json").unwrap();
let config = File::open("config.json")?;
let config = File::open("config.json")
.context("failed to open config")?;
反模式 3:String everywhere
fn greet(name: String) {
println!("Hello, {}", name);
}
fn greet(name: &str) {
println!("Hello, {}", name);
}
反模式 4:索引循环
for i in 0..items.len() {
println!("{}: {}", i, items[i]);
}
for item in &items {
println!("{}", item);
}
for (i, item) in items.iter().enumerate() {
println!("{}: {}", i, item);
}
反模式 5:过度 unsafe
unsafe {
let ptr = data.as_mut_ptr();
}
let mut data: Vec<u8> = vec![0; size];
代码异味速查
| 现象 | 暗示问题 | 重构方向 |
|---|
很多 .clone() | 所有权不清晰 | 明确数据流 |
很多 .unwrap() | 错误处理缺失 | 添加 Result 处理 |
很多 pub 字段 | 封装被破坏 | 私有 + 访问器 |
| 深度嵌套 | 逻辑复杂 | 提取方法 |
| 函数过长 (>50行) | 职责过多 | 拆分职责 |
| 巨大的枚举 | 缺少抽象 | Trait + 类型 |
过时写法 → 现代写法
| 过时 | 现代 |
|---|
索引循环 .items[i] | .iter().enumerate() |
collect::<Vec<_>>() 然后再遍历 | 链式迭代器 |
lazy_static! | std::sync::OnceLock |
mem::transmute 转换 | as 或 TryFrom |
| 自定义链表 | Vec 或 VecDeque |
| 手动 unsafe cell | Cell, RefCell |
代码审查清单
问自己这些问题
-
这段代码在对抗 Rust 还是在配合 Rust?
-
这个 clone 是必要的吗?
-
这个 unwrap 会导致 panic 吗?
- 可能 → 用
?
- 绝不会 →
expect("reason")
-
有更 idiomatic 的方式吗?
- 参考其他 Rust 代码
- 查阅 std 库 API