Rust系统编程 rust-systems

这个技能专注于Rust编程语言中的系统编程核心模式,包括所有权与借用、错误处理、异步运行时、特性与泛型等,用于构建高性能、安全和可维护的软件系统。关键词:Rust, 系统编程, 所有权, 异步, 错误处理, 泛型, 构建器模式。

后端开发 0 次安装 0 次浏览 更新于 3/8/2026

name: rust-systems description: Rust 系统编程模式,包括所有权、特性、异步运行时、错误处理和不安全指南

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);     // 借用:数据仍可用
    let mut owned = take_ownership(data);     // 移动:数据不再可用
    modify_in_place(&mut owned);              // 可变借用
}

优先使用借用(&T&mut T)而非所有权转移。仅在必要时使用 Clone

错误处理

use thiserror::Error;

#[derive(Error, Debug)]
pub enum AppError {
    #[error("数据库错误: {0}")]
    Database(#[from] sqlx::Error),

    #[error("未找到: {resource} 的 id 为 {id}")]
    NotFound { resource: &'static str, id: String },

    #[error("验证失败: {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: "用户",
            id: id.to_string(),
        })
}

库错误使用 thiserror,应用级错误使用 anyhow。生产代码中避免使用 .unwrap()

特性与泛型

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("监听 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
  • [ ] 使用特性进行抽象和可测试性
  • [ ] unsafe 块有记录的安全性不变量
  • [ ] 复杂配置结构使用构建器模式
  • [ ] 启用 Clippy 检查并处理警告