rust-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Rust Best Practices

Rust最佳实践

Apply these guidelines when writing or reviewing Rust code. Based on Apollo GraphQL's Rust Best Practices Handbook.
编写或评审Rust代码时请遵循以下指南。本指南基于Apollo GraphQL的Rust最佳实践手册

Best Practices Reference

最佳实践参考

Before reviewing, familiarize yourself with Apollo's Rust best practices. Read ALL relevant chapters in the same turn in parallel. Reference these files when providing feedback:
  • Chapter 1 - Coding Styles and Idioms: Borrowing vs cloning, Copy trait, Option/Result handling, iterators, comments
  • Chapter 2 - Clippy and Linting: Clippy configuration, important lints, workspace lint setup
  • Chapter 3 - Performance Mindset: Profiling, avoiding redundant clones, stack vs heap, zero-cost abstractions
  • Chapter 4 - Error Handling: Result vs panic, thiserror vs anyhow, error hierarchies
  • Chapter 5 - Automated Testing: Test naming, one assertion per test, snapshot testing
  • Chapter 6 - Generics and Dispatch: Static vs dynamic dispatch, trait objects
  • Chapter 7 - Type State Pattern: Compile-time state safety, when to use it
  • Chapter 8 - Comments vs Documentation: When to comment, doc comments, rustdoc
  • Chapter 9 - Understanding Pointers: Thread safety, Send/Sync, pointer types
评审前,请先熟悉Apollo的Rust最佳实践。同时阅读所有相关章节。提供反馈时请参考以下文件:
  • 第1章 - 编码风格与惯用写法:借用与克隆、Copy trait、Option/Result处理、迭代器、注释
  • 第2章 - Clippy与代码检查:Clippy配置、重要检查项、工作区检查设置
  • 第3章 - 性能思维:性能分析、避免冗余克隆、栈与堆、零成本抽象
  • 第4章 - 错误处理:Result与panic、thiserror与anyhow、错误层级
  • 第5章 - 自动化测试:测试命名、单测试单断言、快照测试
  • 第6章 - 泛型与分发:静态分发与动态分发、 trait对象
  • 第7章 - 类型状态模式:编译时状态安全、适用场景
  • 第8章 - 注释与文档:注释的使用时机、文档注释、rustdoc
  • 第9章 - 指针理解:线程安全、Send/Sync、指针类型

Quick Reference

快速参考

Borrowing & Ownership

借用与所有权

  • Prefer
    &T
    over
    .clone()
    unless ownership transfer is required
  • Use
    &str
    over
    String
    ,
    &[T]
    over
    Vec<T>
    in function parameters
  • Small
    Copy
    types (≤24 bytes) can be passed by value
  • Use
    Cow<'_, T>
    when ownership is ambiguous
  • 除非需要转移所有权,否则优先使用
    &T
    而非
    .clone()
  • 函数参数中优先使用
    &str
    而非
    String
    &[T]
    而非
    Vec<T>
  • 小型
    Copy
    类型(≤24字节)可按值传递
  • 当所有权不明确时,使用
    Cow<'_, T>

Error Handling

错误处理

  • Return
    Result<T, E>
    for fallible operations; avoid
    panic!
    in production
  • Never use
    unwrap()
    /
    expect()
    outside tests
  • Use
    thiserror
    for library errors,
    anyhow
    for binaries only
  • Prefer
    ?
    operator over match chains for error propagation
  • 针对可能失败的操作返回
    Result<T, E>
    ;生产环境中避免使用
    panic!
  • 测试场景外禁止使用
    unwrap()
    /
    expect()
  • 库错误处理使用
    thiserror
    ,仅在二进制程序中使用
    anyhow
  • 错误传播优先使用
    ?
    运算符而非match链式调用

Performance

性能优化

  • Always benchmark with
    --release
    flag
  • Run
    cargo clippy -- -D clippy::perf
    for performance hints
  • Avoid cloning in loops; use
    .iter()
    instead of
    .into_iter()
    for Copy types
  • Prefer iterators over manual loops; avoid intermediate
    .collect()
    calls
  • 始终使用
    --release
    标志进行基准测试
  • 运行
    cargo clippy -- -D clippy::perf
    获取性能提示
  • 避免在循环中克隆;对于Copy类型,使用
    .iter()
    而非
    .into_iter()
  • 优先使用迭代器而非手动循环;避免中间的
    .collect()
    调用

Linting

代码检查

Run regularly:
cargo clippy --all-targets --all-features --locked -- -D warnings
Key lints to watch:
  • redundant_clone
    - unnecessary cloning
  • large_enum_variant
    - oversized variants (consider boxing)
  • needless_collect
    - premature collection
Use
#[expect(clippy::lint)]
over
#[allow(...)]
with justification comment.
定期运行:
cargo clippy --all-targets --all-features --locked -- -D warnings
重点关注的检查项:
  • redundant_clone
    - 不必要的克隆
  • large_enum_variant
    - 过大的枚举变体(考虑装箱)
  • needless_collect
    - 过早的集合操作
优先使用
#[expect(clippy::lint)]
而非
#[allow(...)]
,并附上理由注释。

Testing

测试

  • Name tests descriptively:
    process_should_return_error_when_input_empty()
  • One assertion per test when possible
  • Use doc tests (
    ///
    ) for public API examples
  • Consider
    cargo insta
    for snapshot testing generated output
  • 测试命名要具有描述性:例如
    process_should_return_error_when_input_empty()
  • 尽可能每个测试仅包含一个断言
  • 公共API示例使用文档测试(
    ///
  • 生成的输出可考虑使用
    cargo insta
    进行快照测试

Generics & Dispatch

泛型与分发

  • Prefer generics (static dispatch) for performance-critical code
  • Use
    dyn Trait
    only when heterogeneous collections are needed
  • Box at API boundaries, not internally
  • 性能关键型代码优先使用泛型(静态分发)
  • 仅当需要异构集合时使用
    dyn Trait
  • 在API边界处进行装箱,而非内部

Type State Pattern

类型状态模式

Encode valid states in the type system to catch invalid operations at compile time:
rust
struct Connection<State> { /* ... */ _state: PhantomData<State> }
struct Disconnected;
struct Connected;

impl Connection<Connected> {
    fn send(&self, data: &[u8]) { /* only connected can send */ }
}
在类型系统中编码有效状态,以便在编译时捕获无效操作:
rust
struct Connection<State> { /* ... */ _state: PhantomData<State> }
struct Disconnected;
struct Connected;

impl Connection<Connected> {
    fn send(&self, data: &[u8]) { /* only connected can send */ }
}

Documentation

文档

  • //
    comments explain why (safety, workarounds, design rationale)
  • ///
    doc comments explain what and how for public APIs
  • Every
    TODO
    needs a linked issue:
    // TODO(#42): ...
  • Enable
    #![deny(missing_docs)]
    for libraries
  • //
    注释用于解释原因(安全考量、变通方案、设计依据)
  • ///
    文档注释用于解释公共API的功能使用方式
  • 所有
    TODO
    都需要关联议题:
    // TODO(#42): ...
  • 库中启用
    #![deny(missing_docs)]
    检查