rust-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Rust Best Practices

Rust最佳实践

Unified Rust guidelines covering coding style, ownership, error handling, async patterns, traits, testing, performance, linting, and documentation. Apply when writing or reviewing Rust code.
统一的Rust开发规范,覆盖编码风格、所有权、错误处理、异步模式、trait、测试、性能、lint检查、文档相关内容,在编写或审查Rust代码时遵循使用。

When to Apply

适用场景

  • Writing new Rust code or designing APIs
  • Reviewing or refactoring existing Rust code
  • Implementing async systems with Tokio
  • Designing error hierarchies with thiserror/anyhow
  • Choosing between borrowing, cloning, or ownership transfer
  • Setting up tests, benchmarks, or snapshot testing
  • Configuring clippy lints and workspace settings
  • Optimizing Rust code for performance
  • 编写新的Rust代码或设计API
  • 审查或重构现有Rust代码
  • 使用Tokio实现异步系统
  • 基于thiserror/anyhow设计错误层级结构
  • 在借用、克隆或所有权转移之间做选择
  • 搭建测试、基准测试或快照测试
  • 配置clippy lint规则和工作区设置
  • 对Rust代码进行性能优化

Reference Guide

参考指南

Load detailed guidance based on context. Read the relevant file when the topic arises:
TopicReferenceLoad When
Coding Style
references/coding-style.md
Naming, imports, iterators, comments, string handling, macros
Error Handling
references/error-handling.md
Result, Option, ?, thiserror, anyhow, custom errors, async errors
Ownership & Pointers
references/ownership-and-pointers.md
Lifetimes, borrowing, smart pointers, Pin, Cow, interior mutability
Traits & Generics
references/traits-and-generics.md
Trait design, dispatch, GATs, sealed traits, type state pattern
Async & Concurrency
references/async-and-concurrency.md
Tokio, channels, streams, shutdown, runtime config, async traits
Sync Concurrency
references/concurrency-sync.md
Atomics, Mutex, RwLock, lock ordering, Send/Sync, memory ordering
Testing
references/testing.md
Unit/integration/doc tests, snapshot, proptest, mockall, benchmarks, fuzz
Performance
references/performance.md
Profiling, flamegraph, cloning, stack vs heap, iterators, allocation
Clippy & Linting
references/clippy-and-linting.md
Clippy config, key lints, workspace setup, #[expect] vs #[allow]
Documentation
references/documentation.md
Doc comments, rustdoc, doc lints, coverage checklist
可根据上下文加载详细指引,遇到对应主题时查阅相关文件:
主题参考文档触发加载场景
编码风格
references/coding-style.md
命名、导入、迭代器、注释、字符串处理、宏
错误处理
references/error-handling.md
Result、Option、?、thiserror、anyhow、自定义错误、异步错误
所有权与指针
references/ownership-and-pointers.md
生命周期、借用、智能指针、Pin、Cow、内部可变性
Trait与泛型
references/traits-and-generics.md
Trait设计、分发、GAT、密封trait、类型状态模式
异步与并发
references/async-and-concurrency.md
Tokio、通道、流、优雅关闭、运行时配置、异步trait
同步并发
references/concurrency-sync.md
原子量、Mutex、RwLock、锁顺序、Send/Sync、内存序
测试
references/testing.md
单元/集成/文档测试、快照测试、proptest、mockall、基准测试、模糊测试
性能
references/performance.md
性能分析、火焰图、克隆、栈vs堆、迭代器、内存分配
Clippy与Lint检查
references/clippy-and-linting.md
Clippy配置、核心lint规则、工作区设置、#[expect] vs #[allow]
文档
references/documentation.md
文档注释、rustdoc、文档lint、覆盖率检查清单

Quick Reference: Coding Style

快速参考:编码风格

  • Prefer
    &T
    over
    .clone()
    unless ownership transfer is required
  • Use
    &str
    over
    String
    ,
    &[T]
    over
    Vec<T>
    in function parameters
  • No
    get_
    prefix on getters:
    fn name()
    not
    fn get_name()
  • Conversion naming:
    as_
    (cheap borrow),
    to_
    (expensive/cloning),
    into_
    (ownership transfer)
  • Iterator methods:
    iter()
    /
    iter_mut()
    /
    into_iter()
  • Import ordering:
    std
    -> external crates -> workspace crates ->
    super::
    ->
    crate::
  • Comments explain why (safety, workarounds), not what
  • Use
    format!
    over string concatenation with
    +
  • Prefer
    s.bytes()
    over
    s.chars()
    for ASCII-only operations
  • Avoid macros unless necessary; prefer functions or generics
  • 优先使用
    &T
    而非
    .clone()
    ,除非需要转移所有权
  • 函数参数中优先使用
    &str
    而非
    String
    、优先使用
    &[T]
    而非
    Vec<T>
  • getter方法不要加
    get_
    前缀:用
    fn name()
    而非
    fn get_name()
  • 转换方法命名规则:
    as_
    (低成本借用)、
    to_
    (高成本/克隆)、
    into_
    (所有权转移)
  • 迭代器方法:
    iter()
    /
    iter_mut()
    /
    into_iter()
  • 导入顺序:
    std
    -> 外部 crate -> 工作区内部 crate ->
    super::
    ->
    crate::
  • 注释解释「为什么」(安全性、临时解决方案),而非「做了什么」
  • 使用
    format!
    而非
    +
    做字符串拼接
  • 仅处理ASCII内容时优先用
    s.bytes()
    而非
    s.chars()
  • 除非必要不要用宏,优先选择函数或泛型

Quick Reference: Error Handling

快速参考:错误处理

  • Return
    Result<T, E>
    for fallible operations; reserve
    panic!
    for unrecoverable bugs
  • No
    unwrap()
    in production.
    Use
    expect()
    with descriptive message only when the value is logically guaranteed. Prefer
    ?
    ,
    if let
    ,
    let...else
    for all other cases
  • Use
    thiserror
    for library/crate errors,
    anyhow
    for binaries only
  • Prefer
    ?
    operator over
    match
    chains for error propagation
  • Use
    _else
    variants (
    ok_or_else
    ,
    unwrap_or_else
    ) to prevent eager allocation
  • Use
    inspect_err
    and
    map_err
    for logging and transforming errors
  • assert!
    at function entry for invariant checking (debug builds)
  • 可失败操作返回
    Result<T, E>
    panic!
    仅用于不可恢复的bug
  • 生产代码中禁止使用
    unwrap()
    。仅当值逻辑上必然存在时使用带描述信息的
    expect()
    ,其他所有场景优先用
    ?
    if let
    let...else
  • 库/crate的错误定义用
    thiserror
    ,二进制程序用
    anyhow
  • 错误传播优先用
    ?
    运算符而非
    match
    链式调用
  • 使用
    _else
    变体(
    ok_or_else
    unwrap_or_else
    )避免提前内存分配
  • 错误日志和转换用
    inspect_err
    map_err
  • 函数入口用
    assert!
    做不变性检查(仅Debug构建生效)

Quick Reference: Ownership & Pointers

快速参考:所有权与指针

  • Small
    Copy
    types (<=24 bytes, all fields
    Copy
    , no heap) pass by value
  • Use
    Cow<'_, T>
    when data may or may not need ownership
  • Meaningful lifetime names:
    'src
    ,
    'ctx
    ,
    'conn
    — not just
    'a
  • Use
    try_borrow()
    on
    RefCell
    to avoid panics; prefer over direct
    .borrow_mut()
  • Shadowing for transformations:
    let x = x.parse()?
PointerWhen to Use
Box<T>
Single ownership, heap allocation, recursive types
Rc<T>
Shared ownership, single-threaded
Arc<T>
Shared ownership, multi-threaded
Cell<T>
/
RefCell<T>
Interior mutability, single-threaded
Mutex<T>
/
RwLock<T>
Interior mutability, multi-threaded
  • 小型
    Copy
    类型(<=24字节、所有字段都是
    Copy
    、无堆内存分配)按值传递
  • 数据可能需要也可能不需要所有权时用
    Cow<'_, T>
  • 生命周期命名要有意义:用
    'src
    'ctx
    'conn
    而非无意义的
    'a
  • RefCell
    上优先用
    try_borrow()
    避免panic,不要直接调用
    .borrow_mut()
  • 变量转换用同名遮蔽:
    let x = x.parse()?
指针类型适用场景
Box<T>
单一所有权、堆分配、递归类型
Rc<T>
共享所有权、单线程场景
Arc<T>
共享所有权、多线程场景
Cell<T>
/
RefCell<T>
内部可变性、单线程场景
Mutex<T>
/
RwLock<T>
内部可变性、多线程场景

Quick Reference: Traits & Generics

快速参考:Trait与泛型

  • Prefer generics (static dispatch) by default for zero-cost abstractions
  • Use
    dyn Trait
    only when heterogeneous collections or plugin architectures are needed
  • Box at API boundaries, not internally
  • Object safety: no generic methods, no
    Self: Sized
    , methods use
    &self
    /
    &mut self
    /
    self
  • Use sealed traits to prevent external implementors
  • Type state pattern encodes valid states in the type system:
rust
struct Connection<S> { _state: PhantomData<S> }
struct Disconnected;
struct Connected;
impl Connection<Connected> { fn send(&self, data: &[u8]) { /* ... */ } }
  • 默认优先用泛型(静态分发)实现零成本抽象
  • 仅当需要异构集合或插件架构时使用
    dyn Trait
  • Box仅在API边界使用,不要在内部逻辑使用
  • 对象安全规则:无泛型方法、无
    Self: Sized
    约束、方法使用
    &self
    /
    &mut self
    /
    self
    作为参数
  • 用密封trait禁止外部实现
  • 类型状态模式可在类型系统中编码合法状态:
rust
struct Connection<S> { _state: PhantomData<S> }
struct Disconnected;
struct Connected;
impl Connection<Connected> { fn send(&self, data: &[u8]) { /* ... */ } }

Quick Reference: Async & Concurrency

快速参考:异步与并发

  • Async for I/O-bound work, sync for CPU-bound work
  • Never hold locks across
    .await
    points — use scoped guards
  • Never use
    std::thread::sleep
    in async — use
    tokio::time::sleep
  • Never spawn unboundedly — use semaphores for limits
  • Ensure
    Send
    bounds on spawned futures
  • Use
    JoinSet
    for managing multiple concurrent tasks
  • Use
    CancellationToken
    (from
    tokio_util
    ) for graceful shutdown
  • Instrument with
    tracing
    +
    #[instrument]
    for async debugging
ChannelUse Case
mpsc
Multi-producer, single-consumer message passing
broadcast
Multi-producer, multi-consumer event fan-out
oneshot
Single value, single use (request-response)
watch
Latest-value-only, change notification
  • Sync channels:
    crossbeam::channel
    over
    std::sync::mpsc
  • Async channels:
    tokio::sync::{mpsc, broadcast, oneshot, watch}
  • Atomics (
    AtomicBool
    ,
    AtomicUsize
    ) over
    Mutex
    for primitive types
  • Choose memory ordering carefully:
    Relaxed
    /
    Acquire
    /
    Release
    /
    SeqCst
  • IO密集型工作用异步实现,CPU密集型工作用同步实现
  • 不要在
    .await
    点之间持有锁,使用作用域守卫
  • 异步代码中不要用
    std::thread::sleep
    ,改用
    tokio::time::sleep
  • 不要无限制 spawn 任务,用信号量做并发限制
  • 确保 spawn 的 future 满足
    Send
    约束
  • JoinSet
    管理多个并发任务
  • 优雅关闭用
    tokio_util
    提供的
    CancellationToken
  • 异步调试用
    tracing
    +
    #[instrument]
    做埋点
通道类型适用场景
mpsc
多生产者单消费者消息传递
broadcast
多生产者多消费者事件广播
oneshot
单次单值传递(请求-响应场景)
watch
仅传递最新值、变更通知
  • 同步通道优先用
    crossbeam::channel
    而非
    std::sync::mpsc
  • 异步通道用
    tokio::sync::{mpsc, broadcast, oneshot, watch}
  • 基础类型的同步优先用原子量(
    AtomicBool
    AtomicUsize
    )而非
    Mutex
  • 谨慎选择内存序:
    Relaxed
    /
    Acquire
    /
    Release
    /
    SeqCst

Quick Reference: Testing

快速参考:测试

  • Name tests descriptively:
    process_should_return_error_when_input_empty()
  • One assertion per test when possible; include formatted failure messages
  • Group tests in
    mod
    blocks by unit of work
  • Use doc tests (
    ///
    ) for public API examples; run separately with
    cargo test --doc
  • Snapshot testing:
    cargo insta test
    then
    cargo insta review
    ; redact unstable fields
  • rstest
    for parameterized tests with
    #[case::name]
    labels
  • proptest
    for property-based testing with custom strategies
  • mockall
    with
    #[automock]
    for mocking traits
  • criterion
    for benchmarks with
    iter_batched
    and
    BenchmarkId
  • cargo-fuzz
    with
    libfuzzer_sys
    for fuzz testing
  • cargo-tarpaulin
    or
    cargo-llvm-cov
    for code coverage
  • sqlx::test
    for database integration tests with automatic pool injection
  • Use
    #[should_panic]
    and
    #[ignore]
    attributes where appropriate
  • 测试命名要清晰描述场景:
    process_should_return_error_when_input_empty()
  • 尽可能单测试单断言,包含格式化的失败提示信息
  • 按工作单元将测试分组到
    mod
    块中
  • 公共API示例用文档测试(
    ///
    )编写,可通过
    cargo test --doc
    单独运行
  • 快照测试:执行
    cargo insta test
    后执行
    cargo insta review
    ;对不稳定字段做脱敏处理
  • 参数化测试用
    rstest
    搭配
    #[case::name]
    标签实现
  • 属性测试用
    proptest
    搭配自定义策略实现
  • Trait mock用
    mockall
    搭配
    #[automock]
    实现
  • 基准测试用
    criterion
    搭配
    iter_batched
    BenchmarkId
    实现
  • 模糊测试用
    cargo-fuzz
    搭配
    libfuzzer_sys
    实现
  • 代码覆盖率用
    cargo-tarpaulin
    cargo-llvm-cov
    统计
  • 数据库集成测试用
    sqlx::test
    实现自动连接池注入
  • 合适场景下使用
    #[should_panic]
    #[ignore]
    属性

Quick Reference: Performance

快速参考:性能

  • Golden rule: don't guess, measure. Always benchmark with
    --release
  • Run
    cargo clippy -- -D clippy::perf
    for performance-related hints
  • Use
    cargo flamegraph
    or
    samply
    (macOS) for profiling
  • Avoid cloning in loops; clone at the last moment only
  • Pre-allocate:
    Vec::with_capacity()
    ,
    String::with_capacity()
  • Prefer iterators over manual
    for
    loops; avoid intermediate
    .collect()
  • Stack for small types, heap for large/recursive; use
    smallvec
    for large const arrays
  • Use
    Cow<'_, T>
    to avoid unnecessary allocation
  • Prefer
    s.bytes()
    over
    s.chars()
    for ASCII-only string operations
  • 黄金准则:不要猜测,要实测。基准测试一定要加
    --release
    参数运行
  • 执行
    cargo clippy -- -D clippy::perf
    获取性能相关优化提示
  • 性能分析用
    cargo flamegraph
    samply
    (macOS平台)
  • 避免在循环中做克隆,仅在必要的最后一步克隆
  • 提前分配内存:用
    Vec::with_capacity()
    String::with_capacity()
  • 迭代器优先于手动
    for
    循环;避免不必要的中间
    .collect()
    调用
  • 小型类型用栈存储,大型/递归类型用堆存储;大常量数组用
    smallvec
    优化
  • Cow<'_, T>
    避免不必要的内存分配
  • 仅处理ASCII内容时优先用
    s.bytes()
    而非
    s.chars()

Quick Reference: Clippy & Linting

快速参考:Clippy与Lint检查

Run regularly:
cargo clippy --all-targets --all-features --locked -- -D warnings
LintCatches
redundant_clone
Unnecessary
.clone()
calls
needless_borrow
Unnecessary
&
borrows
large_enum_variant
Oversized variants (consider
Box
)
needless_collect
Premature
.collect()
before iteration
map_unwrap_or
.map().unwrap_or()
chains
unnecessary_wraps
Functions always returning
Ok
/
Some
clone_on_copy
.clone()
on
Copy
types
  • Use
    #[expect(clippy::lint)]
    over
    #[allow(...)]
    expect
    warns when lint no longer applies
  • Add justification comment on every suppression
  • Set
    #![warn(clippy::all)]
    as workspace minimum
  • Configure workspace lints in
    Cargo.toml
    with priority levels
定期执行:
cargo clippy --all-targets --all-features --locked -- -D warnings
Lint规则检测内容
redundant_clone
不必要的
.clone()
调用
needless_borrow
不必要的
&
借用
large_enum_variant
过大的枚举变体(建议用
Box
包装)
needless_collect
迭代前提前执行
.collect()
map_unwrap_or
.map().unwrap_or()
链式调用
unnecessary_wraps
函数总是返回
Ok
/
Some
clone_on_copy
Copy
类型调用
.clone()
  • 优先用
    #[expect(clippy::lint)]
    而非
    #[allow(...)]
    ——当lint规则不再触发时
    expect
    会给出警告
  • 每一条lint抑制都要加注释说明理由
  • 工作区最低配置为
    #![warn(clippy::all)]
  • Cargo.toml
    中配置工作区lint规则和优先级

Quick Reference: Documentation

快速参考:文档

  • //
    comments explain why: safety invariants, workarounds, design rationale
  • ///
    doc comments explain what and how for all public items
  • //!
    for module-level and crate-level documentation at top of
    lib.rs
    /
    mod.rs
  • Every
    TODO
    needs a linked issue:
    // TODO(#42): description
  • Enable
    #![deny(missing_docs)]
    for libraries
  • Include
    # Examples
    ,
    # Errors
    ,
    # Panics
    ,
    # Safety
    sections in doc comments
Doc LintPurpose
missing_docs
Ensure all public items documented
broken_intra_doc_links
Catch dead cross-references
missing_panics_doc
Document panic conditions
missing_errors_doc
Document error conditions
missing_safety_doc
Document unsafe safety requirements
  • //
    注释解释「为什么」:安全不变性、临时解决方案、设计 rationale
  • ///
    文档注释解释所有公共项的「是什么」和「怎么用」
  • 模块级和crate级文档用
    //!
    写在
    lib.rs
    /
    mod.rs
    顶部
  • 每个
    TODO
    都要关联issue:
    // TODO(#42): 描述
  • 库代码启用
    #![deny(missing_docs)]
    校验
  • 文档注释中包含
    # 示例
    # 错误
    # Panic
    # 安全性
    章节
文档Lint规则用途
missing_docs
确保所有公共项都有文档
broken_intra_doc_links
检测失效的内部文档链接
missing_panics_doc
要求说明panic触发条件
missing_errors_doc
要求说明错误触发条件
missing_safety_doc
要求说明unsafe代码的安全约束

Quick Reference: Data Types & Patterns

快速参考:数据类型与模式

  • Use newtypes for domain semantics:
    struct Email(String)
  • Prefer slice patterns:
    if let [first, .., last] = slice
  • Use arrays for fixed sizes; avoid
    Vec
    when length is known at compile time
  • Shadowing for transformation:
    let x = x.parse()?
  • Cow<str>
    when data might need modification of borrowed data
  • contains()
    on strings is O(n*m) — avoid nested string iteration
  • 领域语义用新类型实现:
    struct Email(String)
  • 优先用切片模式:
    if let [first, .., last] = slice
  • 固定长度的集合用数组,编译时已知长度时不要用
    Vec
  • 变量转换用同名遮蔽:
    let x = x.parse()?
  • 可能需要修改借用数据时用
    Cow<str>
  • 字符串
    contains()
    是O(n*m)复杂度,避免嵌套字符串遍历

Deprecated to Modern Migration

弃用特性迁移指南

DeprecatedBetterSince
lazy_static!
std::sync::OnceLock
Rust 1.70
once_cell::Lazy
std::sync::LazyLock
Rust 1.80
std::sync::mpsc
crossbeam::channel
(sync)
std::sync::Mutex
parking_lot::Mutex
(recommended)
failure
/
error-chain
thiserror
/
anyhow
try!()
?
operator
Rust 2018
async-trait
crate
Native
async fn
in traits (1.75+, limited)
Rust 1.75
弃用用法推荐替代起始版本
lazy_static!
std::sync::OnceLock
Rust 1.70
once_cell::Lazy
std::sync::LazyLock
Rust 1.80
std::sync::mpsc
crossbeam::channel
(同步场景)
std::sync::Mutex
parking_lot::Mutex
(推荐)
failure
/
error-chain
thiserror
/
anyhow
try!()
?
运算符
Rust 2018
async-trait
crate
trait原生
async fn
(1.75+,功能有限)
Rust 1.75

Cargo.toml Essentials

Cargo.toml核心配置

Recommended dependencies:
toml
[dependencies]
thiserror = "2"
anyhow = "1"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
tracing = "0.1"
tracing-subscriber = "0.3"

[dev-dependencies]
rstest = "0.25"
proptest = "1"
mockall = "0.13"
criterion = { version = "0.5", features = ["html_reports"] }
insta = { version = "1", features = ["yaml"] }
Workspace lints (
Cargo.toml
):
toml
[workspace.lints.clippy]
all = { level = "warn", priority = -1 }
pedantic = { level = "warn", priority = -1 }
rustfmt.toml
:
toml
reorder_imports = true
imports_granularity = "Crate"
group_imports = "StdExternalCrate"
推荐依赖:
toml
[dependencies]
thiserror = "2"
anyhow = "1"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
tracing = "0.1"
tracing-subscriber = "0.3"

[dev-dependencies]
rstest = "0.25"
proptest = "1"
mockall = "0.13"
criterion = { version = "0.5", features = ["html_reports"] }
insta = { version = "1", features = ["yaml"] }
工作区Lint配置(
Cargo.toml
):
toml
[workspace.lints.clippy]
all = { level = "warn", priority = -1 }
pedantic = { level = "warn", priority = -1 }
rustfmt.toml
配置:
toml
reorder_imports = true
imports_granularity = "Crate"
group_imports = "StdExternalCrate"

Constraints

约束规则

MUST DO

必须遵守

  1. Use ownership and borrowing for memory safety
  2. Handle all errors explicitly via
    Result
    /
    Option
    — no silent failures
  3. Use
    thiserror
    for library errors,
    anyhow
    for binaries
  4. Minimize
    unsafe
    code; document all
    unsafe
    blocks with safety invariants
  5. Use the type system for compile-time guarantees
  6. Run
    cargo clippy
    and fix all warnings
  7. Use
    cargo fmt
    for consistent formatting
  8. Write tests including doc tests for public APIs
  9. Add
    ///
    documentation with examples for all public items
  10. Use
    tracing
    for observability in async code
  11. When reviewing or writing code, suggest a testing approach using the recommended tools (
    rstest
    ,
    proptest
    ,
    insta
    ,
    mockall
    ,
    criterion
    ) — even if the user did not ask for tests
  1. 使用所有权和借用保证内存安全
  2. 所有错误都通过
    Result
    /
    Option
    显式处理——禁止静默失败
  3. 库错误用
    thiserror
    定义,二进制程序用
    anyhow
    处理错误
  4. 尽量减少
    unsafe
    代码;所有
    unsafe
    块都要加注释说明安全不变性
  5. 利用类型系统实现编译时校验
  6. 执行
    cargo clippy
    并修复所有警告
  7. cargo fmt
    保证代码格式统一
  8. 编写测试,包含公共API的文档测试
  9. 所有公共项都要有带示例的
    ///
    文档
  10. 异步代码用
    tracing
    实现可观测性
  11. 审查或编写代码时,即使用户没有要求测试,也要给出基于推荐工具(
    rstest
    proptest
    insta
    mockall
    criterion
    )的测试方案建议

MUST NOT DO

禁止操作

  1. Use
    unwrap()
    in production code
  2. Create memory leaks or dangling pointers
  3. Use
    unsafe
    without documented safety invariants
  4. Ignore clippy warnings without
    #[expect(...)]
    and justification
  5. Hold locks across
    .await
    points
  6. Use
    std::thread::sleep
    in async context
  7. Skip error handling or use
    panic!
    for recoverable errors
  8. Use
    String
    where
    &str
    suffices; clone unnecessarily
  9. Spawn tasks unboundedly without semaphore limits
  10. Mix blocking and async code without
    spawn_blocking
  1. 生产代码中使用
    unwrap()
  2. 造成内存泄漏或悬垂指针
  3. 使用
    unsafe
    但不标注安全不变性说明
  4. 忽略clippy警告,且没有
    #[expect(...)]
    标注和理由说明
  5. .await
    点之间持有锁
  6. 在异步上下文使用
    std::thread::sleep
  7. 跳过错误处理,或用
    panic!
    处理可恢复错误
  8. 可用
    &str
    的场景用
    String
    ;做不必要的克隆
  9. 没有信号量限制就无限制 spawn 任务
  10. 不使用
    spawn_blocking
    就混合阻塞代码和异步代码