关于 rust-systems
面向 Rust 开发者的系统编程技能指南,涵盖所有权、错误处理、Trait、异步模式、配置构建与常见问题。
主要功能
- 01所有权与借用指导
- 02使用 thiserror 和 anyhow 处理错误
- 03Trait 与泛型
- 04有界异步并发
- 05配置的构建器模式
- 06反模式与检查清单
适用场景
- 01检查 Rust 代码中的不必要克隆
- 02设计库和应用的错误类型
- 03实现有界并发的异步任务
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ rohitg00/ awesome-claude-code-toolkit --skill rust-systems安装后在 Claude Code 中输入/rust-systems确认已加载。
详细介绍
Rust 系统编程
所有权与借用
fn process_data(data: &[u8]) -> Vec<u8> {
data.iter().map(|b| b.wrapping_add(1)).collect()
}
fn modify_in_place(data: &mut Vec<u8>) {
data.retain(|b| *b != 0);
data.sort_unstable();
}
fn take_ownership(data: Vec<u8>) -> Vec<u8> {
let mut result = data;
result.push(0xFF);
result
}
fn main() {
let data = vec![1, 2, 3, 0, 4];
let processed = process_data(&data); // borrow: data still usable
let mut owned = take_ownership(data); // move: data no longer usable
modify_in_place(&mut owned); // mutable borrow
}
优先使用借用(&T、&mut T),而非转移所有权。仅在必要时使用 Clone。
错误处理
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AppError {
#[error("database error: {0}")]
Database(#[from] sqlx::Error),
#[error("not found: {resource} with id {id}")]
NotFound { resource: &'static str, id: String },
#[error("validation failed: {0}")]
Validation(String),
}
type Result<T> = std::result::Result<T, AppError>;
async fn get_user(pool: &PgPool, id: &str) -> Result<User> {
sqlx::query_as::<_, User>("SELECT * FROM users WHERE id = $1")
.bind(id)
.fetch_optional(pool)
.await?
.ok_or_else(|| AppError::NotFound {
resource: "User",
id: id.to_string(),
})
}
库错误使用 thiserror,应用级错误使用 anyhow。避免在生产代码中使用 .unwrap()。
Trait 与泛型
trait Repository {
type Item;
type Error;
async fn find_by_id(&self, id: &str) -> std::result::Result<Option<Self::Item>, Self::Error>;
async fn save(&self, item: &Self::Item) -> std::result::Result<(), Self::Error>;
}
struct PgUserRepo {
pool: PgPool,
}
impl Repository for PgUserRepo {
type Item = User;
type Error = AppError;
async fn find_by_id(&self, id: &str) -> Result<Option<User>> {
let user = sqlx::query_as::<_, User>("SELECT * FROM users WHERE id = $1")
.bind(id)
.fetch_optional(&self.pool)
.await?;
Ok(user)
}
async fn save(&self, user: &User) -> Result<()> {
sqlx::query("INSERT INTO users (id, name, email) VALUES ($1, $2, $3)")
.bind(&user.id)
.bind(&user.name)
.bind(&user.email)
.execute(&self.pool)
.await?;
Ok(())
}
}
异步模式
use tokio::sync::Semaphore;
use futures::stream::{self, StreamExt};
async fn fetch_all(urls: Vec<String>, max_concurrent: usize) -> Vec<Result<String>> {
let semaphore = Arc::new(Semaphore::new(max_concurrent));
stream::iter(urls)
.map(|url| {
let sem = semaphore.clone();
async move {
let _permit = sem.acquire().await.unwrap();
reqwest::get(&url).await?.text().await.map_err(Into::into)
}
})
.buffer_unordered(max_concurrent)
.collect()
.await
}
async fn graceful_shutdown(handle: tokio::runtime::Handle) {
let ctrl_c = tokio::signal::ctrl_c();
ctrl_c.await.expect("Failed to listen for Ctrl+C");
handle.shutdown_timeout(std::time::Duration::from_secs(30));
}
构建器模式
pub struct ServerConfig {
host: String,
port: u16,
workers: usize,
tls: bool,
}
pub struct ServerConfigBuilder {
host: String,
port: u16,
workers: usize,
tls: bool,
}
impl ServerConfigBuilder {
pub fn new() -> Self {
Self { host: "0.0.0.0".into(), port: 8080, workers: 4, tls: false }
}
pub fn host(mut self, host: impl Into<String>) -> Self { self.host = host.into(); self }
pub fn port(mut self, port: u16) -> Self { self.port = port; self }
pub fn workers(mut self, n: usize) -> Self { self.workers = n; self }
pub fn tls(mut self, enabled: bool) -> Self { self.tls = enabled; self }
pub fn build(self) -> ServerConfig {
ServerConfig { host: self.host, port: self.port, workers: self.workers, tls: self.tls }
}
}
反模式
- 在库代码中使用
.unwrap()或.expect() - 不必要地克隆数据,而不使用借用
- 在
.await处持有MutexGuard(会导致死锁) - 在通道更合适时使用
Arc<Mutex<Vec<T>>> - 编写
unsafe代码却不记录不变量 - 未在返回 Result 的函数上使用
#[must_use]
检查清单
- 使用
thiserror定义错误类型,并使用?运算符传播错误 - 生产代码路径中没有
.unwrap() - 所有权模型尽量减少克隆
- 异步代码使用有界并发(信号量或
buffer_unordered) - 使用 Trait 实现抽象并提升可测试性
-
unsafe代码块记录了安全不变量 - 复杂配置结构体使用构建器模式
- 启用了 Clippy lint 并处理了警告
评论
支持 Markdown