Rust 编码指南(50 条核心规则)
命名(Rust 特定)
| 规则 | 指南 |
|---|
不使用 get_ 前缀 | fn name(),而不是 fn get_name() |
| 迭代器约定 | iter() / iter_mut() / into_iter() |
| 转换命名 | as_(廉价且借用)、to_(开销较大)、into_(转移所有权) |
| 静态变量前缀 | static 使用 G_CONFIG,const 不加前缀 |
数据类型
| 规则 | 指南 |
|---|
| 使用新类型 | 用 struct Email(String) 表示领域语义 |
| 优先使用切片模式 | if let [first, .., last] = slice |
| 预先分配 | Vec::with_capacity()、String::with_capacity() |
| 避免滥用 Vec | 固定大小使用数组 |
字符串
| 规则 | 指南 |
|---|
| 优先使用字节 | ASCII 场景下使用 s.bytes(),而不是 s.chars() |
使用 Cow<str> | 可能需要修改借用数据时 |
使用 format! | 优先于使用 + 拼接字符串 |
| 避免嵌套迭代 | 字符串上的 contains() 的复杂度为 O(n*m) |
错误处理
| 规则 | 指南 |
|---|
使用 ? 传播错误 | 不使用 try!() 宏 |
值有保证时使用 expect() | 优先于 unwrap() |
| 使用断言表达不变量 | 在函数入口处使用 assert! |
内存
| 规则 | 指南 |
|---|
| 使用有意义的生命周期名 | 使用 'src、'ctx,而不只是 'a |
对 RefCell 使用 try_borrow() | 避免 panic |
| 转换时使用变量遮蔽 | let x = x.parse()? |
并发
| 规则 | 指南 |
|---|
| 明确锁的获取顺序 | 防止死锁 |
| 基本类型使用原子类型 | 不要对 bool/usize 使用 Mutex |
| 谨慎选择内存顺序 | Relaxed/Acquire/Release/SeqCst |
异步
| 规则 | 指南 |
|---|
| CPU 密集型任务使用同步代码 | 异步适用于 I/O |
| 不要在 await 期间持有锁 | 使用作用域守卫 |
宏
| 规则 | 指南 |
|---|
| 非必要时避免使用 | 优先使用函数/泛型 |
| 遵循 Rust 语法 | 宏输入应符合 Rust 语法 |
已弃用 → 更佳替代方案
| 已弃用 | 更佳替代方案 | 版本 |
|---|
lazy_static! | std::sync::OnceLock | 1.70 |
once_cell::Lazy | std::sync::LazyLock | 1.80 |
std::sync::mpsc | crossbeam::channel | - |
std::sync::Mutex | parking_lot::Mutex | - |
failure/error-chain | thiserror/anyhow | - |
try!() | ? 运算符 | 2018 |
快速参考
Naming: snake_case (fn/var), CamelCase (type), SCREAMING_CASE (const)
Format: rustfmt (just use it)
Docs: /// for public items, //! for module docs
Lint: #![warn(clippy::all)]
Claude 非常了解 Rust 约定。以下是一些不太显而易见的 Rust 特定规则。