
Rust 的生态系统就像一个大超市——东西多到你逛一天都逛不完,但知道该买啥才是关键!
学 Rust 三个月后,我面临一个重大问题:
"我知道怎么用 Rust 写代码了,但...我该用哪些库啊?!"
这感觉就像:
Rust 的生态系统(ecosystem)这几年发展得飞快, crates.io(Rust 的包管理器)上已经有 10 万+ 个 crate(库)!
今天我就帮你从这 10 万+ 个库里,挑出最常用、最靠谱的那些,让你少走弯路!
crate = Rust 的"库"或"包"
生活化类比:
概念 | 类比 |
|---|---|
crate | 乐高积木套装 |
cargo | 乐高商店(可以买/卖套装) |
crates.io | 乐高官网(所有套装的目录) |
Cargo.toml | 购物清单(记录你要买哪些套装) |
Rust 库
├── 标准库(std)- 自带干粮
├── 官方推荐库 - 亲儿子
└── 第三方库 - 社区贡献
├── 基础设施类(web、数据库、序列化)
├── 工具类(日期、随机数、命令行)
└── 领域特定类(游戏、嵌入式、AI)
选库三原则:
💡 查库工具:
Rust 标准库虽然"小",但都是精华!
std::collections - 数据结构全家桶use std::collections::{HashMap, HashSet, VecDeque, BTreeMap};
fn main() {
// HashMap - 键值对存储(最常用)
let mut scores = HashMap::new();
scores.insert("Larry", );
scores.insert("Sarah", );
// HashSet - 去重神器
let mut unique_numbers = HashSet::new();
unique_numbers.insert();
unique_numbers.insert(); // 重复的会被忽略
unique_numbers.insert();
println!("{:?}", unique_numbers); // [1, 2]
// VecDeque - 双端队列(可以头尾都插入)
let mut deque = VecDeque::new();
deque.push_front();
deque.push_back();
// BTreeMap - 有序 Map(按 key 排序)
let mut sorted = BTreeMap::new();
sorted.insert(, "three");
sorted.insert(, "one");
// 遍历时会按 key 排序:1, 3
}
std::io - 输入输出use std::io::{self, Read, Write};
use std::fs::File;
fn main() -> io::Result<()> {
// 读取文件
let mut file = File::open("hello.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
// 写入文件
let mut output = File::create("output.txt")?;
write!(output, "Hello, World!")?;
// 读取用户输入
let mut input = String::new();
io::stdin().read_line(&mut input)?;
Ok(())
}
std::sync - 并发工具use std::sync::{Arc, Mutex, RwLock};
use std::thread;
fn main() {
// Arc - 线程安全的引用计数
let counter = Arc::new(Mutex::new());
// Mutex - 互斥锁(同一时间只有一个线程能访问)
let mut handles = vec![];
for _ in .. {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += ;
});
handles.push(handle);
}
// RwLock - 读写锁(读可以多线程,写要独占)
let data = RwLock::new(vec![, , ]);
// 读(可以多个同时)
let read_guard = data.read().unwrap();
println!("{:?}", *read_guard);
// 写(要独占)
let mut write_guard = data.write().unwrap();
write_guard.push();
}
1. serde - 序列化/反序列化
# Cargo.toml
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]
struct User {
name: String,
age: u32,
email: String,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let user = User {
name: "Larry".to_string(),
age: ,
email: "larry@example.com".to_string(),
};
// 序列化为 JSON
let json = serde_json::to_string(&user)?;
println!("{}", json);
// {"name":"Larry","age":25,"email":"larry@example.com"}
// 反序列化
let user2: User = serde_json::from_str(&json)?;
println!("{:?}", user2);
Ok(())
}
2. tokio - 异步运行时
[dependencies]
tokio = { version = "1", features = ["full"] }
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
println!("开始异步任务...");
// 异步等待 2 秒
sleep(Duration::from_secs()).await;
println!("2 秒后我醒了!");
// 并发执行多个任务
let task1 = tokio::spawn(async {
println!("任务 1 开始");
sleep(Duration::from_secs()).await;
println!("任务 1 完成");
});
let task2 = tokio::spawn(async {
println!("任务 2 开始");
sleep(Duration::from_secs()).await;
println!("任务 2 完成");
});
// 等待所有任务完成
let _ = tokio::join!(task1, task2);
}
3. reqwest - HTTP 客户端
[dependencies]
reqwest = { version = "0.11", features = ["json"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
use reqwest::Client;
use serde::Deserialize;
#[derive(Deserialize, Debug)]
struct Post {
userId: u32,
id: u32,
title: String,
body: String,
}
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new();
// GET 请求
let response = client
.get("https://jsonplaceholder.typicode.com/posts/1")
.send()
.await?
.json::<Post>()
.await?;
println!("{:?}", response);
// POST 请求
let new_post = serde_json::json!({
"title": "我的新文章",
"body": "这是内容",
"userId":
});
let created = client
.post("https://jsonplaceholder.typicode.com/posts")
.json(&new_post)
.send()
.await?
.json::<Post>()
.await?;
println!("创建成功:{:?}", created);
Ok(())
}
4. clap - 命令行参数解析
[dependencies]
clap = { version = "4.0", features = ["derive"] }
use clap::Parser;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// 要处理的文件
#[arg(short, long)]
file: String,
/// 输出格式
#[arg(short, long, default_value = "text")]
format: String,
/// 是否详细输出
#[arg(short, long)]
verbose: bool,
}
fn main() {
let args = Args::parse();
println!("文件:{}", args.file);
println!("格式:{}", args.format);
println!("详细模式:{}", args.verbose);
}
使用效果:
$ ./myapp --file input.txt --format json --verbose
文件:input.txt
格式:json
详细模式:true
5. anyhow & thiserror - 错误处理
[dependencies]
anyhow = "1.0"
thiserror = "1.0"
use anyhow::{Context, Result};
use thiserror::Error;
// 自定义错误类型
#[derive(Error, Debug)]
enum MyError {
#[error("文件未找到:{0}")]
FileNotFound(String),
#[error("解析失败:{0}")]
ParseError(String),
}
// 使用 anyhow 的简单方式
fn read_config() -> Result<String> {
let content = std::fs::read_to_string("config.toml")
.context("读取配置文件失败")?;
Ok(content)
}
// 使用 thiserror 的自定义错误
fn parse_value(input: &str) -> std::result::Result<i32, MyError> {
input
.parse()
.map_err(|e| MyError::ParseError(e.to_string()))
}
fn main() -> Result<()> {
let config = read_config()?;
println!("配置:{}", config);
Ok(())
}
Web 开发:
[dependencies]
# Web 框架(三选一)
axum = "0.7" # 轻量、灵活
actix-web = "4" # 性能怪兽
rocket = "0.5" # 易用性最好
# 模板引擎
askama = "0.12" # 类型安全
tera = "1" # Jinja2 风格
# 会话管理
axum-sessions = "0.5"
数据库:
[dependencies]
# SQL 库(二选一)
sqlx = { version = "0.7", features = ["runtime-tokio-native-tls", "postgres"] }
diesel = { version = "2.1", features = ["postgres"] }
# Redis
redis = "0.23"
# MongoDB
mongodb = "2.8"
日期时间:
[dependencies]
chrono = "0.4" # 经典选择
time = "0.3" # 现代替代
随机数:
[dependencies]
rand = "0.8"
日志:
[dependencies]
tracing = "0.1"
tracing-subscriber = "0.3"
env_logger = "0.10"
测试:
[dev-dependencies]
mockall = "0.11" # Mock 框架
criterion = "0.5" # 基准测试
proptest = "1.3" # 属性测试
问题: 两个库依赖不同版本的同一个库
error: failed to select a version for `tokio`.
... required by package `lib_a v1.0.0`
... which satisfies dependency `lib_a = "^1.0"` of package `my_app`
...
versions that meet the requirements `^0.2` are: 0.2.0
versions that meet the requirements `^1.0` are: 1.0.0
解决:
[dependencies]
# 统一指定版本
tokio = { version = "1.0", features = ["full"] }
问题: 编译报错说某个功能不存在
error[E0432]: unresolved import `tokio::fs`
|
= note: the `fs` feature is required for this import
解决:
[dependencies]
tokio = { version = "1", features = ["full", "fs"] }
问题: 直接用 * 或者不指定版本
[dependencies]
some-crate = "*" # ❌ 不要这样!
解决: 用语义化版本
[dependencies]
some-crate = "1.2" # ✅ 兼容 1.2.x
Cargo.toml:
[package]
name = "my-api"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = "0.7"
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sqlx = { version = "0.7", features = ["runtime-tokio-native-tls", "postgres"] }
tracing = "0.1"
tracing-subscriber = "0.3"
anyhow = "1.0"
main.rs:
use axum::{
extract::State,
http::StatusCode,
response::Json,
routing::{get, post},
Router,
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::Mutex;
// 应用状态
#[derive(Clone)]
struct AppState {
db: Arc<Mutex<Vec<User>>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct User {
id: u32,
name: String,
email: String,
}
#[derive(Deserialize)]
struct CreateUser {
name: String,
email: String,
}
#[tokio::main]
async fn main() {
// 初始化日志
tracing_subscriber::fmt::init();
// 初始化状态
let db = Arc::new(Mutex::new(vec![]));
let state = AppState { db };
// 路由
let app = Router::new()
.route("/users", get(list_users))
.route("/users", post(create_user))
.with_state(state);
// 启动服务
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
.await
.unwrap();
tracing::info!("服务器启动在端口 3000");
axum::serve(listener, app).await.unwrap();
}
async fn list_users(
State(state): State<AppState>,
) -> Json<Vec<User>> {
let users = state.db.lock().await;
Json(users.clone())
}
async fn create_user(
State(state): State<AppState>,
Json(payload): Json<CreateUser>,
) -> Result<Json<User>, StatusCode> {
let mut db = state.db.lock().await;
let user = User {
id: db.len() as u32 + ,
name: payload.name,
email: payload.email,
};
db.push(user.clone());
Ok(Json(user))
}
这个案例用到的库:
axum - Web 框架tokio - 异步运行时serde - 序列化tracing - 日志anyhow - 错误处理一个典型的现代 Rust Web 项目栈!

核心要点:
collections、io、sync 必须熟练掌握*金句时间:
"好的程序员不是知道所有库,而是知道该查哪个库。"
下篇预告: 第 49 篇咱们来聊聊调试技巧 - 代码跑不起来怎么办?println 调试太 low?gdb/lldb 怎么用?IDE 有哪些神器?敬请期待!