强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Rust 系统编程语言完全教程 / 第21章:Crates 生态

第21章:Crates 生态

21.1 crates.io 简介

crates.io 是 Rust 的官方包注册中心,类似于 Python 的 PyPI、Node.js 的 npm。

查找 crate

平台 网址 说明
crates.io https://crates.io 官方注册中心
lib.rs https://lib.rs 更好的搜索和分类
docs.rs https://docs.rs 自动生成的文档
deps.rs https://deps.rs 依赖新鲜度检查

选择 crate 的标准

  1. 下载量: 月下载量高通常更可靠
  2. 维护状态: 最近有更新
  3. 文档质量: 有完整文档和示例
  4. 测试覆盖: 有测试用例
  5. 许可证: MIT/Apache-2.0 最常见
  6. 依赖数量: 依赖越少越好

21.2 serde:序列化框架

基本用法

[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct User {
    name: String,
    email: String,
    age: u32,
    #[serde(default)]
    active: bool,
}

fn main() {
    let user = User {
        name: "Alice".to_string(),
        email: "alice@example.com".to_string(),
        age: 30,
        active: true,
    };

    // 序列化到 JSON
    let json = serde_json::to_string_pretty(&user).unwrap();
    println!("JSON:\n{}", json);

    // 从 JSON 反序列化
    let json_str = r#"{"name":"Bob","email":"bob@example.com","age":25}"#;
    let user2: User = serde_json::from_str(json_str).unwrap();
    println!("反序列化: {:?}", user2);
}

serde 属性

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Config {
    #[serde(rename = "serverHost")]
    host: String,

    #[serde(default = "default_port")]
    port: u16,

    #[serde(skip_serializing_if = "Option::is_none")]
    password: Option<String>,

    #[serde(skip)]
    internal: bool,
}

fn default_port() -> u16 {
    8080
}

21.3 tokio:异步运行时

基本功能

[dependencies]
tokio = { version = "1", features = ["full"] }
use tokio::time::{sleep, Duration};
use tokio::fs;

#[tokio::main]
async fn main() {
    // 异步文件操作
    fs::write("test.txt", "hello").await.unwrap();
    let content = fs::read_to_string("test.txt").await.unwrap();
    println!("文件内容: {}", content);

    // 并发任务
    let mut handles = vec![];
    for i in 0..5 {
        handles.push(tokio::spawn(async move {
            sleep(Duration::from_millis(100 * i)).await;
            format!("任务{}完成", i)
        }));
    }

    for handle in handles {
        println!("{}", handle.await.unwrap());
    }

    // 清理
    let _ = fs::remove_file("test.txt").await;
}

Tokio 功能模块

模块 功能
tokio::fs 异步文件操作
tokio::net TCP/UDP 网络
tokio::sync 异步同步原语
tokio::time 定时器和超时
tokio::signal 信号处理
tokio::process 异步进程管理
tokio::io 异步 I/O traits

21.4 reqwest:HTTP 客户端

[dependencies]
reqwest = { version = "0.12", features = ["json"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
use serde::Deserialize;

#[derive(Deserialize, Debug)]
struct Todo {
    id: u32,
    title: String,
    completed: bool,
}

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    // GET 请求
    let todos: Vec<Todo> = reqwest::get("https://jsonplaceholder.typicode.com/todos?_limit=5")
        .await?
        .json()
        .await?;

    for todo in &todos {
        println!("[{}] {}", if todo.completed { "✓" } else { " " }, todo.title);
    }

    // POST 请求
    let client = reqwest::Client::new();
    let new_todo = serde_json::json!({
        "title": "学习 Rust",
        "completed": false,
        "userId": 1
    });

    let resp = client.post("https://jsonplaceholder.typicode.com/todos")
        .json(&new_todo)
        .send()
        .await?;

    println!("创建状态: {}", resp.status());

    Ok(())
}

21.5 clap:命令行解析

[dependencies]
clap = { version = "4", features = ["derive"] }
use clap::Parser;

#[derive(Parser, Debug)]
#[command(name = "mytool")]
#[command(about = "一个示例命令行工具")]
struct Args {
    /// 输入文件
    #[arg(short, long)]
    input: String,

    /// 输出文件(可选)
    #[arg(short, long, default_value = "output.txt")]
    output: String,

    /// 详细模式
    #[arg(short, long)]
    verbose: bool,

    /// 并发数
    #[arg(short, long, default_value_t = 4)]
    workers: usize,
}

fn main() {
    let args = Args::parse();

    println!("输入: {}", args.input);
    println!("输出: {}", args.output);
    println!("详细: {}", args.verbose);
    println!("并发: {}", args.workers);
}

21.6 常用 crate 速查表

Web 开发

crate 用途 说明
axum Web 框架 Tokio 团队维护,类型安全
actix-web Web 框架 高性能
rocket Web 框架 易用
tower 中间件 服务抽象层
hyper HTTP 底层 HTTP 实现

数据库

crate 用途 说明
sqlx SQL 异步、编译时检查
diesel ORM 类型安全的 ORM
sea-orm ORM 异步 ORM
redis Redis Redis 客户端

序列化

crate 用途 说明
serde 序列化框架 必备
serde_json JSON JSON 支持
toml TOML 配置文件
bincode 二进制 高效二进制格式

日志与监控

crate 用途 说明
tracing 日志 结构化日志
tracing-subscriber 日志 订阅者实现
log 日志 简单日志 facade
env_logger 日志 环境变量配置

工具类

crate 用途 说明
anyhow 错误处理 应用级错误
thiserror 错误处理 自定义错误
chrono 日期时间 日期处理
regex 正则表达式 正则匹配
uuid UUID 唯一标识符
rand 随机数 随机数生成

21.7 业务场景示例

CLI + HTTP + JSON 综合

[dependencies]
clap = { version = "4", features = ["derive"] }
reqwest = { version = "0.12", features = ["json"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
anyhow = "1"
use clap::Parser;
use serde::Deserialize;
use anyhow::Result;

#[derive(Parser)]
#[command(name = "weather")]
struct Args {
    /// 城市名
    city: String,
}

#[derive(Deserialize, Debug)]
struct WeatherResponse {
    location: Location,
    current: Current,
}

#[derive(Deserialize, Debug)]
struct Location {
    name: String,
    country: String,
}

#[derive(Deserialize, Debug)]
struct Current {
    temp_c: f64,
    condition: Condition,
}

#[derive(Deserialize, Debug)]
struct Condition {
    text: String,
}

#[tokio::main]
async fn main() -> Result<()> {
    let args = Args::parse();

    // 注意:需要替换为真实的 API key
    println!("查询 {} 的天气...", args.city);
    println!("(示例输出)");
    println!("城市: {}", args.city);
    println!("温度: 25.0°C");
    println!("天气: 晴朗");

    Ok(())
}

21.8 本章小结

要点 说明
crates.io Rust 官方包注册中心
serde 必备序列化库
tokio 最流行的异步运行时
reqwest HTTP 客户端
clap 命令行参数解析
选择标准 下载量、维护状态、文档质量

扩展阅读

  1. crates.io — 包注册中心
  2. lib.rs — 更好的 crate 搜索
  3. Blessed.rs — 推荐 crate 集合