Rust 系统编程语言完全教程 / 第21章:Crates 生态
第21章:Crates 生态
21.1 crates.io 简介
crates.io 是 Rust 的官方包注册中心,类似于 Python 的 PyPI、Node.js 的 npm。
查找 crate
选择 crate 的标准
- 下载量: 月下载量高通常更可靠
- 维护状态: 最近有更新
- 文档质量: 有完整文档和示例
- 测试覆盖: 有测试用例
- 许可证: MIT/Apache-2.0 最常见
- 依赖数量: 依赖越少越好
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 | 命令行参数解析 |
| 选择标准 | 下载量、维护状态、文档质量 |
扩展阅读
- crates.io — 包注册中心
- lib.rs — 更好的 crate 搜索
- Blessed.rs — 推荐 crate 集合