rust-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Rust Development Patterns

Rust 开发模式

Idiomatic Rust patterns and best practices for building safe, performant, and maintainable applications.
构建安全、高性能且可维护应用的地道Rust编程模式与最佳实践。

When to Use

适用场景

  • Writing new Rust code
  • Reviewing Rust code
  • Refactoring existing Rust code
  • Designing crate structure and module layout
  • 编写新的Rust代码
  • 评审Rust代码
  • 重构现有Rust代码
  • 设计Crate结构与模块布局

How It Works

工作原理

This skill enforces idiomatic Rust conventions across six key areas: ownership and borrowing to prevent data races at compile time,
Result
/
?
error propagation with
thiserror
for libraries and
anyhow
for applications, enums and exhaustive pattern matching to make illegal states unrepresentable, traits and generics for zero-cost abstraction, safe concurrency via
Arc<Mutex<T>>
, channels, and async/await, and minimal
pub
surfaces organized by domain.
本技能在六大核心领域强制执行地道的Rust规范:通过所有权与借用在编译期防止数据竞争;在库中使用
Result
/
?
结合
thiserror
进行错误传播,在应用中使用
anyhow
;使用枚举与穷举模式匹配让非法状态无法被表示;使用特性与泛型实现零成本抽象;通过
Arc<Mutex<T>>
、通道和async/await实现安全并发;按领域组织最小化的
pub
对外接口。

Core Principles

核心原则

1. Ownership and Borrowing

1. 所有权与借用

Rust's ownership system prevents data races and memory bugs at compile time.
rust
// Good: Pass references when you don't need ownership
fn process(data: &[u8]) -> usize {
    data.len()
}

// Good: Take ownership only when you need to store or consume
fn store(data: Vec<u8>) -> Record {
    Record { payload: data }
}

// Bad: Cloning unnecessarily to avoid borrow checker
fn process_bad(data: &Vec<u8>) -> usize {
    let cloned = data.clone(); // Wasteful — just borrow
    cloned.len()
}
Rust的所有权系统可在编译期防止数据竞争与内存漏洞。
rust
// 推荐:不需要所有权时传递引用
fn process(data: &[u8]) -> usize {
    data.len()
}

// 推荐:仅在需要存储或消费时获取所有权
fn store(data: Vec<u8>) -> Record {
    Record { payload: data }
}

// 不推荐:为规避借用检查器而不必要地克隆
fn process_bad(data: &Vec<u8>) -> usize {
    let cloned = data.clone(); // 浪费资源 — 只需借用即可
    cloned.len()
}

Use
Cow
for Flexible Ownership

使用
Cow
实现灵活所有权

rust
use std::borrow::Cow;

fn normalize(input: &str) -> Cow<'_, str> {
    if input.contains(' ') {
        Cow::Owned(input.replace(' ', "_"))
    } else {
        Cow::Borrowed(input) // Zero-cost when no mutation needed
    }
}
rust
use std::borrow::Cow;

fn normalize(input: &str) -> Cow<'_, str> {
    if input.contains(' ') {
        Cow::Owned(input.replace(' ', "_"))
    } else {
        Cow::Borrowed(input) // 无需修改时零成本
    }
}

Error Handling

错误处理

Use
Result
and
?
— Never
unwrap()
in Production

使用
Result
?
— 生产环境中绝不使用
unwrap()

rust
// Good: Propagate errors with context
use anyhow::{Context, Result};

fn load_config(path: &str) -> Result<Config> {
    let content = std::fs::read_to_string(path)
        .with_context(|| format!("failed to read config from {path}"))?;
    let config: Config = toml::from_str(&content)
        .with_context(|| format!("failed to parse config from {path}"))?;
    Ok(config)
}

// Bad: Panics on error
fn load_config_bad(path: &str) -> Config {
    let content = std::fs::read_to_string(path).unwrap(); // Panics!
    toml::from_str(&content).unwrap()
}
rust
// 推荐:携带上下文传播错误
use anyhow::{Context, Result};

fn load_config(path: &str) -> Result<Config> {
    let content = std::fs::read_to_string(path)
        .with_context(|| format!("从 {path} 读取配置失败"))?;
    let config: Config = toml::from_str(&content)
        .with_context(|| format!("解析 {path} 中的配置失败"))?;
    Ok(config)
}

// 不推荐:发生错误时直接恐慌
fn load_config_bad(path: &str) -> Config {
    let content = std::fs::read_to_string(path).unwrap(); // 会恐慌!
    toml::from_str(&content).unwrap()
}

Library Errors with
thiserror
, Application Errors with
anyhow

库错误使用
thiserror
,应用错误使用
anyhow

rust
// Library code: structured, typed errors
use thiserror::Error;

#[derive(Debug, Error)]
pub enum StorageError {
    #[error("record not found: {id}")]
    NotFound { id: String },
    #[error("connection failed")]
    Connection(#[from] std::io::Error),
    #[error("invalid data: {0}")]
    InvalidData(String),
}

// Application code: flexible error handling
use anyhow::{bail, Result};

fn run() -> Result<()> {
    let config = load_config("app.toml")?;
    if config.workers == 0 {
        bail!("worker count must be > 0");
    }
    Ok(())
}
rust
// 库代码:结构化、类型化错误
use thiserror::Error;

#[derive(Debug, Error)]
pub enum StorageError {
    #[error("记录未找到:{id}")]
    NotFound { id: String },
    #[error("连接失败")]
    Connection(#[from] std::io::Error),
    #[error("无效数据:{0}")]
    InvalidData(String),
}

// 应用代码:灵活的错误处理
use anyhow::{bail, Result};

fn run() -> Result<()> {
    let config = load_config("app.toml")?;
    if config.workers == 0 {
        bail!("工作进程数必须大于 0");
    }
    Ok(())
}

Option
Combinators Over Nested Matching

使用
Option
组合子替代嵌套匹配

rust
// Good: Combinator chain
fn find_user_email(users: &[User], id: u64) -> Option<String> {
    users.iter()
        .find(|u| u.id == id)
        .map(|u| u.email.clone())
}

// Bad: Deeply nested matching
fn find_user_email_bad(users: &[User], id: u64) -> Option<String> {
    match users.iter().find(|u| u.id == id) {
        Some(user) => match &user.email {
            email => Some(email.clone()),
        },
        None => None,
    }
}
rust
// 推荐:组合子链式调用
fn find_user_email(users: &[User], id: u64) -> Option<String> {
    users.iter()
        .find(|u| u.id == id)
        .map(|u| u.email.clone())
}

// 不推荐:深层嵌套匹配
fn find_user_email_bad(users: &[User], id: u64) -> Option<String> {
    match users.iter().find(|u| u.id == id) {
        Some(user) => match &user.email {
            email => Some(email.clone()),
        },
        None => None,
    }
}

Enums and Pattern Matching

枚举与模式匹配

Model States as Enums

用枚举建模状态

rust
// Good: Impossible states are unrepresentable
enum ConnectionState {
    Disconnected,
    Connecting { attempt: u32 },
    Connected { session_id: String },
    Failed { reason: String, retries: u32 },
}

fn handle(state: &ConnectionState) {
    match state {
        ConnectionState::Disconnected => connect(),
        ConnectionState::Connecting { attempt } if *attempt > 3 => abort(),
        ConnectionState::Connecting { .. } => wait(),
        ConnectionState::Connected { session_id } => use_session(session_id),
        ConnectionState::Failed { retries, .. } if *retries < 5 => retry(),
        ConnectionState::Failed { reason, .. } => log_failure(reason),
    }
}
rust
// 推荐:非法状态无法被表示
enum ConnectionState {
    Disconnected,
    Connecting { attempt: u32 },
    Connected { session_id: String },
    Failed { reason: String, retries: u32 },
}

fn handle(state: &ConnectionState) {
    match state {
        ConnectionState::Disconnected => connect(),
        ConnectionState::Connecting { attempt } if *attempt > 3 => abort(),
        ConnectionState::Connecting { .. } => wait(),
        ConnectionState::Connected { session_id } => use_session(session_id),
        ConnectionState::Failed { retries, .. } if *retries < 5 => retry(),
        ConnectionState::Failed { reason, .. } => log_failure(reason),
    }
}

Exhaustive Matching — No Catch-All for Business Logic

穷举匹配 — 业务逻辑中不要使用通配符

rust
// Good: Handle every variant explicitly
match command {
    Command::Start => start_service(),
    Command::Stop => stop_service(),
    Command::Restart => restart_service(),
    // Adding a new variant forces handling here
}

// Bad: Wildcard hides new variants
match command {
    Command::Start => start_service(),
    _ => {} // Silently ignores Stop, Restart, and future variants
}
rust
// 推荐:显式处理每个变体
match command {
    Command::Start => start_service(),
    Command::Stop => stop_service(),
    Command::Restart => restart_service(),
    // 添加新变体时必须在此处处理
}

// 不推荐:通配符会隐藏新变体
match command {
    Command::Start => start_service(),
    _ => {} // 静默忽略Stop、Restart及未来新增的变体
}

Traits and Generics

特性与泛型

Accept Generics, Return Concrete Types

接受泛型,返回具体类型

rust
// Good: Generic input, concrete output
fn read_all(reader: &mut impl Read) -> std::io::Result<Vec<u8>> {
    let mut buf = Vec::new();
    reader.read_to_end(&mut buf)?;
    Ok(buf)
}

// Good: Trait bounds for multiple constraints
fn process<T: Display + Send + 'static>(item: T) -> String {
    format!("processed: {item}")
}
rust
// 推荐:泛型输入,具体输出
fn read_all(reader: &mut impl Read) -> std::io::Result<Vec<u8>> {
    let mut buf = Vec::new();
    reader.read_to_end(&mut buf)?;
    Ok(buf)
}

// 推荐:为多个约束添加 trait 边界
fn process<T: Display + Send + 'static>(item: T) -> String {
    format!("已处理:{item}")
}

Trait Objects for Dynamic Dispatch

特性对象用于动态分发

rust
// Use when you need heterogeneous collections or plugin systems
trait Handler: Send + Sync {
    fn handle(&self, request: &Request) -> Response;
}

struct Router {
    handlers: Vec<Box<dyn Handler>>,
}

// Use generics when you need performance (monomorphization)
fn fast_process<H: Handler>(handler: &H, request: &Request) -> Response {
    handler.handle(request)
}
rust
// 当需要异构集合或插件系统时使用
trait Handler: Send + Sync {
    fn handle(&self, request: &Request) -> Response;
}

struct Router {
    handlers: Vec<Box<dyn Handler>>,
}

// 需要高性能时使用泛型(单态化)
fn fast_process<H: Handler>(handler: &H, request: &Request) -> Response {
    handler.handle(request)
}

Newtype Pattern for Type Safety

Newtype 模式实现类型安全

rust
// Good: Distinct types prevent mixing up arguments
struct UserId(u64);
struct OrderId(u64);

fn get_order(user: UserId, order: OrderId) -> Result<Order> {
    // Can't accidentally swap user and order IDs
    todo!()
}

// Bad: Easy to swap arguments
fn get_order_bad(user_id: u64, order_id: u64) -> Result<Order> {
    todo!()
}
rust
// 推荐:不同类型防止参数混淆
struct UserId(u64);
struct OrderId(u64);

fn get_order(user: UserId, order: OrderId) -> Result<Order> {
    // 不会意外交换用户ID和订单ID
    todo!()
}

// 不推荐:容易交换参数
fn get_order_bad(user_id: u64, order_id: u64) -> Result<Order> {
    todo!()
}

Structs and Data Modeling

结构体与数据建模

Builder Pattern for Complex Construction

构建器模式用于复杂对象构造

rust
struct ServerConfig {
    host: String,
    port: u16,
    max_connections: usize,
}

impl ServerConfig {
    fn builder(host: impl Into<String>, port: u16) -> ServerConfigBuilder {
        ServerConfigBuilder { host: host.into(), port, max_connections: 100 }
    }
}

struct ServerConfigBuilder { host: String, port: u16, max_connections: usize }

impl ServerConfigBuilder {
    fn max_connections(mut self, n: usize) -> Self { self.max_connections = n; self }
    fn build(self) -> ServerConfig {
        ServerConfig { host: self.host, port: self.port, max_connections: self.max_connections }
    }
}

// Usage: ServerConfig::builder("localhost", 8080).max_connections(200).build()
rust
struct ServerConfig {
    host: String,
    port: u16,
    max_connections: usize,
}

impl ServerConfig {
    fn builder(host: impl Into<String>, port: u16) -> ServerConfigBuilder {
        ServerConfigBuilder { host: host.into(), port, max_connections: 100 }
    }
}

struct ServerConfigBuilder { host: String, port: u16, max_connections: usize }

impl ServerConfigBuilder {
    fn max_connections(mut self, n: usize) -> Self { self.max_connections = n; self }
    fn build(self) -> ServerConfig {
        ServerConfig { host: self.host, port: self.port, max_connections: self.max_connections }
    }
}

// 使用方式:ServerConfig::builder("localhost", 8080).max_connections(200).build()

Iterators and Closures

迭代器与闭包

Prefer Iterator Chains Over Manual Loops

优先使用迭代器链而非手动循环

rust
// Good: Declarative, lazy, composable
let active_emails: Vec<String> = users.iter()
    .filter(|u| u.is_active)
    .map(|u| u.email.clone())
    .collect();

// Bad: Imperative accumulation
let mut active_emails = Vec::new();
for user in &users {
    if user.is_active {
        active_emails.push(user.email.clone());
    }
}
rust
// 推荐:声明式、惰性求值、可组合
let active_emails: Vec<String> = users.iter()
    .filter(|u| u.is_active)
    .map(|u| u.email.clone())
    .collect();

// 不推荐:命令式累加
let mut active_emails = Vec::new();
for user in &users {
    if user.is_active {
        active_emails.push(user.email.clone());
    }
}

Use
collect()
with Type Annotation

结合类型注解使用
collect()

rust
// Collect into different types
let names: Vec<_> = items.iter().map(|i| &i.name).collect();
let lookup: HashMap<_, _> = items.iter().map(|i| (i.id, i)).collect();
let combined: String = parts.iter().copied().collect();

// Collect Results — short-circuits on first error
let parsed: Result<Vec<i32>, _> = strings.iter().map(|s| s.parse()).collect();
rust
// 收集为不同类型
let names: Vec<_> = items.iter().map(|i| &i.name).collect();
let lookup: HashMap<_, _> = items.iter().map(|i| (i.id, i)).collect();
let combined: String = parts.iter().copied().collect();

// 收集Result — 第一个错误出现时立即终止
let parsed: Result<Vec<i32>, _> = strings.iter().map(|s| s.parse()).collect();

Concurrency

并发编程

Arc<Mutex<T>>
for Shared Mutable State

使用
Arc<Mutex<T>>
实现共享可变状态

rust
use std::sync::{Arc, Mutex};

let counter = Arc::new(Mutex::new(0));
let handles: Vec<_> = (0..10).map(|_| {
    let counter = Arc::clone(&counter);
    std::thread::spawn(move || {
        let mut num = counter.lock().expect("mutex poisoned");
        *num += 1;
    })
}).collect();

for handle in handles {
    handle.join().expect("worker thread panicked");
}
rust
use std::sync::{Arc, Mutex};

let counter = Arc::new(Mutex::new(0));
let handles: Vec<_> = (0..10).map(|_| {
    let counter = Arc::clone(&counter);
    std::thread::spawn(move || {
        let mut num = counter.lock().expect("互斥锁已中毒");
        *num += 1;
    })
}).collect();

for handle in handles {
    handle.join().expect("工作线程恐慌");
}

Channels for Message Passing

使用通道进行消息传递

rust
use std::sync::mpsc;

let (tx, rx) = mpsc::sync_channel(16); // Bounded channel with backpressure

for i in 0..5 {
    let tx = tx.clone();
    std::thread::spawn(move || {
        tx.send(format!("message {i}")).expect("receiver disconnected");
    });
}
drop(tx); // Close sender so rx iterator terminates

for msg in rx {
    println!("{msg}");
}
rust
use std::sync::mpsc;

let (tx, rx) = mpsc::sync_channel(16); // 带背压的有界通道

for i in 0..5 {
    let tx = tx.clone();
    std::thread::spawn(move || {
        tx.send(format!("消息 {i}")).expect("接收端已断开连接");
    });
}
drop(tx); // 关闭发送端,使rx迭代器终止

for msg in rx {
    println!("{msg}");
}

Async with Tokio

使用Tokio实现异步编程

rust
use tokio::time::Duration;

async fn fetch_with_timeout(url: &str) -> Result<String> {
    let response = tokio::time::timeout(
        Duration::from_secs(5),
        reqwest::get(url),
    )
    .await
    .context("request timed out")?
    .context("request failed")?;

    response.text().await.context("failed to read body")
}

// Spawn concurrent tasks
async fn fetch_all(urls: Vec<String>) -> Vec<Result<String>> {
    let handles: Vec<_> = urls.into_iter()
        .map(|url| tokio::spawn(async move {
            fetch_with_timeout(&url).await
        }))
        .collect();

    let mut results = Vec::with_capacity(handles.len());
    for handle in handles {
        results.push(handle.await.unwrap_or_else(|e| panic!("spawned task panicked: {e}")));
    }
    results
}
rust
use tokio::time::Duration;

async fn fetch_with_timeout(url: &str) -> Result<String> {
    let response = tokio::time::timeout(
        Duration::from_secs(5),
        reqwest::get(url),
    )
    .await
    .context("请求超时")?
    .context("请求失败")?;

    response.text().await.context("读取响应体失败")
}

// 生成并发任务
async fn fetch_all(urls: Vec<String>) -> Vec<Result<String>> {
    let handles: Vec<_> = urls.into_iter()
        .map(|url| tokio::spawn(async move {
            fetch_with_timeout(&url).await
        }))
        .collect();

    let mut results = Vec::with_capacity(handles.len());
    for handle in handles {
        results.push(handle.await.unwrap_or_else(|e| panic!("生成的任务恐慌:{e}")));
    }
    results
}

Unsafe Code

不安全代码

When Unsafe Is Acceptable

可接受的不安全代码场景

rust
// Acceptable: FFI boundary with documented invariants (Rust 2024+)
/// # Safety
/// `ptr` must be a valid, aligned pointer to an initialized `Widget`.
unsafe fn widget_from_raw<'a>(ptr: *const Widget) -> &'a Widget {
    // SAFETY: caller guarantees ptr is valid and aligned
    unsafe { &*ptr }
}

// Acceptable: Performance-critical path with proof of correctness
// SAFETY: index is always < len due to the loop bound
unsafe { slice.get_unchecked(index) }
rust
// 可接受:FFI边界,带有文档化的不变量(Rust 2024+)
/// # 安全性
/// `ptr` 必须是指向已初始化 `Widget` 的有效、对齐指针。
unsafe fn widget_from_raw<'a>(ptr: *const Widget) -> &'a Widget {
    // 安全性:调用者保证ptr有效且对齐
    unsafe { &*ptr }
}

// 可接受:性能关键路径,且有正确性证明
// 安全性:由于循环边界,index始终小于len
unsafe { slice.get_unchecked(index) }

When Unsafe Is NOT Acceptable

不可接受的不安全代码场景

rust
// Bad: Using unsafe to bypass borrow checker
// Bad: Using unsafe for convenience
// Bad: Using unsafe without a Safety comment
// Bad: Transmuting between unrelated types
rust
// 不推荐:使用unsafe规避借用检查器
// 不推荐:为了方便使用unsafe
// 不推荐:使用unsafe但无Safety注释
// 不推荐:在不相关类型之间进行转换

Module System and Crate Structure

模块系统与Crate结构

Organize by Domain, Not by Type

按领域组织,而非按类型

text
my_app/
├── src/
│   ├── main.rs
│   ├── lib.rs
│   ├── auth/          # Domain module
│   │   ├── mod.rs
│   │   ├── token.rs
│   │   └── middleware.rs
│   ├── orders/        # Domain module
│   │   ├── mod.rs
│   │   ├── model.rs
│   │   └── service.rs
│   └── db/            # Infrastructure
│       ├── mod.rs
│       └── pool.rs
├── tests/             # Integration tests
├── benches/           # Benchmarks
└── Cargo.toml
text
my_app/
├── src/
│   ├── main.rs
│   ├── lib.rs
│   ├── auth/          # 领域模块
│   │   ├── mod.rs
│   │   ├── token.rs
│   │   └── middleware.rs
│   ├── orders/        # 领域模块
│   │   ├── mod.rs
│   │   ├── model.rs
│   │   └── service.rs
│   └── db/            # 基础设施
│       ├── mod.rs
│       └── pool.rs
├── tests/             # 集成测试
├── benches/           # 基准测试
└── Cargo.toml

Visibility — Expose Minimally

可见性 — 最小化对外暴露

rust
// Good: pub(crate) for internal sharing
pub(crate) fn validate_input(input: &str) -> bool {
    !input.is_empty()
}

// Good: Re-export public API from lib.rs
pub mod auth;
pub use auth::AuthMiddleware;

// Bad: Making everything pub
pub fn internal_helper() {} // Should be pub(crate) or private
rust
// 推荐:使用pub(crate)进行内部共享
pub(crate) fn validate_input(input: &str) -> bool {
    !input.is_empty()
}

// 推荐:在lib.rs中重新导出公共API
pub mod auth;
pub use auth::AuthMiddleware;

// 不推荐:将所有内容设为pub
pub fn internal_helper() {} // 应该设为pub(crate)或私有

Tooling Integration

工具集成

Essential Commands

必备命令

bash
undefined
bash
undefined

Build and check

构建与检查

cargo build cargo check # Fast type checking without codegen cargo clippy # Lints and suggestions cargo fmt # Format code
cargo build cargo check # 快速类型检查,无需生成代码 cargo clippy # 代码检查与建议 cargo fmt # 代码格式化

Testing

测试

cargo test cargo test -- --nocapture # Show println output cargo test --lib # Unit tests only cargo test --test integration # Integration tests only
cargo test cargo test -- --nocapture # 显示println输出 cargo test --lib # 仅运行单元测试 cargo test --test integration # 仅运行集成测试

Dependencies

依赖管理

cargo audit # Security audit cargo tree # Dependency tree cargo update # Update dependencies
cargo audit # 安全审计 cargo tree # 依赖树 cargo update # 更新依赖

Performance

性能测试

cargo bench # Run benchmarks
undefined
cargo bench # 运行基准测试
undefined

Quick Reference: Rust Idioms

速查:Rust惯用写法

IdiomDescription
Borrow, don't clonePass
&T
instead of cloning unless ownership is needed
Make illegal states unrepresentableUse enums to model valid states only
?
over
unwrap()
Propagate errors, never panic in library/production code
Parse, don't validateConvert unstructured data to typed structs at the boundary
Newtype for type safetyWrap primitives in newtypes to prevent argument swaps
Prefer iterators over loopsDeclarative chains are clearer and often faster
#[must_use]
on Results
Ensure callers handle return values
Cow
for flexible ownership
Avoid allocations when borrowing suffices
Exhaustive matchingNo wildcard
_
for business-critical enums
Minimal
pub
surface
Use
pub(crate)
for internal APIs
惯用写法描述
优先借用,避免克隆无需所有权时传递
&T
而非克隆
让非法状态无法被表示使用枚举仅建模有效状态
?
替代
unwrap()
传播错误,绝不在库或生产代码中恐慌
解析而非验证在边界处将非结构化数据转换为类型化结构体
使用Newtype实现类型安全将基本类型包装为新类型,防止参数混淆
优先使用迭代器而非循环声明式链更清晰且通常更快
对Result使用
#[must_use]
确保调用者处理返回值
使用
Cow
实现灵活所有权
无需修改时避免分配
穷举匹配业务关键枚举不使用通配符
_
最小化
pub
对外接口
对内部API使用
pub(crate)

Anti-Patterns to Avoid

需避免的反模式

rust
// Bad: .unwrap() in production code
let value = map.get("key").unwrap();

// Bad: .clone() to satisfy borrow checker without understanding why
let data = expensive_data.clone();
process(&original, &data);

// Bad: Using String when &str suffices
fn greet(name: String) { /* should be &str */ }

// Bad: Box<dyn Error> in libraries (use thiserror instead)
fn parse(input: &str) -> Result<Data, Box<dyn std::error::Error>> { todo!() }

// Bad: Ignoring must_use warnings
let _ = validate(input); // Silently discarding a Result

// Bad: Blocking in async context
async fn bad_async() {
    std::thread::sleep(Duration::from_secs(1)); // Blocks the executor!
    // Use: tokio::time::sleep(Duration::from_secs(1)).await;
}
Remember: If it compiles, it's probably correct — but only if you avoid
unwrap()
, minimize
unsafe
, and let the type system work for you.
rust
// 不推荐:生产代码中使用.unwrap()
let value = map.get("key").unwrap();

// 不推荐:为满足借用检查器而盲目克隆,却不理解原因
let data = expensive_data.clone();
process(&original, &data);

// 不推荐:可用&str时使用String
fn greet(name: String) { /* 应改为&str */ }

// 不推荐:库中使用Box<dyn Error>(应使用thiserror)
fn parse(input: &str) -> Result<Data, Box<dyn std::error::Error>> { todo!() }

// 不推荐:忽略must_use警告
let _ = validate(input); // 静默丢弃Result

// 不推荐:在异步上下文阻塞
async fn bad_async() {
    std::thread::sleep(Duration::from_secs(1)); // 会阻塞执行器!
    // 应使用:tokio::time::sleep(Duration::from_secs(1)).await;
}
请记住:如果代码能编译通过,那么它很可能是正确的 — 但前提是你避免使用
unwrap()
、最小化
unsafe
代码,并让类型系统为你工作。