Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
// Good: Pass references when you don't need ownershipfnprocess(data: &[u8]) ->usize {
data.len()
}
// Good: Take ownership only when you need to store or consumefnstore(data: Vec<u8>) -> Record {
Record { payload: data }
}
// Bad: Cloning unnecessarily to avoid borrow checkerfnprocess_bad(data: &<>) {
= data.();
cloned.()
}
Vec
u8
->
usize
let
cloned
clone
// Wasteful — just borrow
len
使用 Cow 实现灵活的所有权
use std::borrow::Cow;
fnnormalize(input: &str) -> Cow<'_, str> {
if input.contains(' ') {
Cow::Owned(input.replace(' ', "_"))
} else {
Cow::Borrowed(input) // Zero-cost when no mutation needed
}
}
错误处理
使用 Result 和 ? —— 切勿在生产环境中使用 unwrap()
// Good: Propagate errors with contextuse anyhow::{Context, Result};
fnload_config(path: &str) ->Result<Config> {
letcontent = std::fs::read_to_string(path)
.with_context(|| format!("failed to read config from {path}"))?;
letconfig: Config = toml::from_str(&content)
.with_context(|| format!("failed to parse config from {path}"))?;
Ok(config)
}
// Bad: Panics on errorfnload_config_bad(path: &str) -> Config {
letcontent = std::fs::read_to_string(path).unwrap(); // Panics!
toml::from_str(&content).unwrap()
}
// Use when you need heterogeneous collections or plugin systemstraitHandler: Send + Sync {
fnhandle(&self, request: &Request) -> Response;
}
structRouter {
handlers: Vec<Box<dyn Handler>>,
}
// Use generics when you need performance (monomorphization)fnfast_process<H: Handler>(handler: &H, request: &Request) -> Response {
handler.handle(request)
}
使用 Newtype 模式确保类型安全
// Good: Distinct types prevent mixing up argumentsstructUserId(u64);
structOrderId(u64);
fnget_order(user: UserId, order: OrderId) ->Result<Order> {
// Can't accidentally swap user and order IDs
todo!()
}
// Bad: Easy to swap argumentsfnget_order_bad(user_id: u64, order_id: u64) ->Result<Order> {
todo!()
}
// Acceptable: FFI boundary with documented invariants (Rust 2024+)/// # Safety/// `ptr` must be a valid, aligned pointer to an initialized `Widget`.unsafefnwidget_from_raw<'a>(ptr: *const Widget) -> &'a Widget {
// SAFETY: caller guarantees ptr is valid and alignedunsafe { &*ptr }
}
// Acceptable: Performance-critical path with proof of correctness// SAFETY: index is always < len due to the loop boundunsafe { slice.get_unchecked(index) }
何时不可以使用 Unsafe
// Bad: Using unsafe to bypass borrow checker// Bad: Using unsafe for convenience// Bad: Using unsafe without a Safety comment// Bad: Transmuting between unrelated types
// Good: pub(crate) for internal sharingpub(crate) fnvalidate_input(input: &str) ->bool {
!input.is_empty()
}
// Good: Re-export public API from lib.rspubmod auth;
pubuse auth::AuthMiddleware;
// Bad: Making everything pubpubfninternal_helper() {} // Should be pub(crate) or private
工具集成
基本命令
# Build and check
cargo build
cargo check # Fast type checking without codegen
cargo clippy # Lints and suggestions
cargo fmt# Format code# Testing
cargo test
cargo test -- --nocapture # Show println output
cargo test --lib # Unit tests only
cargo test --test integration # Integration tests only# Dependencies
cargo audit # Security audit
cargo tree # Dependency tree
cargo update # Update dependencies# Performance
cargo bench # Run benchmarks
快速参考:Rust 惯用法
惯用法
描述
借用,而非克隆
传递 &T,除非需要所有权,否则不要克隆
使非法状态无法表示
使用枚举仅对有效状态进行建模
? 优于 unwrap()
传播错误,切勿在库/生产代码中恐慌
解析,而非验证
在边界处将非结构化数据转换为类型化结构体
Newtype 用于类型安全
将基本类型包装在 newtype 中以防止参数错位
优先使用迭代器而非循环
声明式链更清晰且通常更快
对 Result 使用 #[must_use]
确保调用者处理返回值
使用 Cow 实现灵活的所有权
当借用足够时避免分配
穷尽匹配
业务关键枚举不使用通配符 _
最小化 pub 接口
内部 API 使用 pub(crate)
应避免的反模式
// Bad: .unwrap() in production codeletvalue = map.get("key").unwrap();
// Bad: .clone() to satisfy borrow checker without understanding whyletdata = expensive_data.clone();
process(&original, &data);
// Bad: Using String when &str sufficesfngreet(name: String) { /* should be &str */ }
// Bad: Box<dyn Error> in libraries (use thiserror instead)fnparse(input: &str) ->Result<Data, Box<dyn std::error::Error>> { todo!() }
// Bad: Ignoring must_use warningslet_ = validate(input); // Silently discarding a Result// Bad: Blocking in async contextasyncfnbad_async() {
std::thread::sleep(Duration::from_secs(1)); // Blocks the executor!// Use: tokio::time::sleep(Duration::from_secs(1)).await;
}