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

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

第21章:Crates 生态

21.1 crates.io 简介

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

查找 crate

平台网址说明
crates.iohttps://crates.io官方注册中心
lib.rshttps://lib.rs更好的搜索和分类
docs.rshttps://docs.rs自动生成的文档
deps.rshttps://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: "[email protected]".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":"[email protected]","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::netTCP/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用途说明
axumWeb 框架Tokio 团队维护,类型安全
actix-webWeb 框架高性能
rocketWeb 框架易用
tower中间件服务抽象层
hyperHTTP底层 HTTP 实现

数据库

crate用途说明
sqlxSQL异步、编译时检查
dieselORM类型安全的 ORM
sea-ormORM异步 ORM
redisRedisRedis 客户端

序列化

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

日志与监控

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

工具类

crate用途说明
anyhow错误处理应用级错误
thiserror错误处理自定义错误
chrono日期时间日期处理
regex正则表达式正则匹配
uuidUUID唯一标识符
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.ioRust 官方包注册中心
serde必备序列化库
tokio最流行的异步运行时
reqwestHTTP 客户端
clap命令行参数解析
选择标准下载量、维护状态、文档质量

扩展阅读

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