目录
1. Rust 设计哲学
Rust 的设计目标是在不依赖垃圾回收器(GC)的前提下,提供内存安全和零成本抽象。这是通过编译时的所有权检查(Borrow Checker)来实现的,而非运行时的额外开销。
// Rust 可以同时兼顾安全与性能
fn process_data(data: Vec<u8>) -> Vec<u8> {
data.into_iter()
.map(|b| b.wrapping_add(1))
.collect()
}
与 C/C++ 相比,Rust 消除了整类运行时错误(use-after-free、double-free、data race);与 Java/Go 相比,Rust 没有 GC 停顿,内存布局完全可控。
2. 所有权与借用
2.1 三条核心规则
- 每个值有且只有一个所有者(owner)
- 当所有者离开作用域,值被自动释放(通过
Droptrait) - 所有权可以转移(move)或借用(borrow)
fn main() {
let s1 = String::from("hello");
let s2 = s1; // 所有权 move 到 s2
// println!("{}", s1); // 错误!s1 已失效
println!("{}", s2);
} // s2 离开作用域,String 被释放
2.2 不可变借用 vs 可变借用
fn main() {
let mut s = String::from("hello");
let r1 = &s; // 不可变借用
let r2 = &s; // ✅ 多个不可变借用允许
// let r3 = &mut s; // ❌ 与不可变借用冲突
println!("{} {}", r1, r2);
let r3 = &mut s; // ✅ 之前借用已结束
r3.push_str(" world");
}
规则:在同一作用域内,要么有多个不可变引用,要么只有一个可变引用,不可兼得。
2.3 Copy vs Clone
let x = 5;
let y = x; // ✅ Copy trait:按位复制,x 仍可用
let s1 = String::from("hi");
let s2 = s1.clone(); // Clone trait:深拷贝,s1 仍可用
2.4 智能指针简介
| 类型 | 用途 | 线程安全 |
|---|---|---|
Box<T> | 堆分配 | - |
Rc<T> | 单线程引用计数共享 | ❌ |
Arc<T> | 多线程原子引用计数 | ✅ |
RefCell<T> | 运行时借用检查(单线程内部可变性) | ❌ |
Mutex<T> / RwLock<T> | 线程安全内部可变性 | ✅ |
use std::rc::Rc;
use std::cell::RefCell;
let shared = Rc::new(RefCell::new(0));
let clone1 = Rc::clone(&shared);
let clone2 = Rc::clone(&shared);
*clone1.borrow_mut() += 1;
*clone2.borrow_mut() += 1;
println!("{}", shared.borrow()); // 2
3. 生命周期系统
生命周期确保引用不会指向已被释放的内存。
3.1 显式生命周期标注
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
'a 表示返回的引用生命周期不大于输入参数的最短生命周期。
3.2 生命周期省略规则(Elision)
编译器自动推断的常见情况:
fn first_word(s: &str) -> &str { /* 自动推断:输入和输出同生命周期 */ }
fn get_by_key<'a>(&'a self, key: &str) -> &'a Value { /* 输出绑定 self */ }
3.3 结构体中的生命周期
struct Parser<'a> {
text: &'a str,
pos: usize,
}
impl<'a> Parser<'a> {
fn peek(&self) -> Option<&'a str> {
self.text.get(self.pos..self.pos + 1)
}
}
3.4 ‘static 生命周期
let s: &'static str = "编译期字符串"; // 存储在二进制中
// 或 Box::leak 产生的堆内存
let leaked: &'static str = Box::leak(String::from("hello").into_boxed_str());
4. Trait 与面向接口编程
Trait 是 Rust 的接口机制,定义共享行为。
4.1 定义与实现
trait Drawable {
fn draw(&self);
fn bounds(&self) -> (f64, f64, f64, f64) {
(0.0, 0.0, 100.0, 100.0) // 默认实现
}
}
struct Circle { radius: f64 }
impl Drawable for Circle {
fn draw(&self) { println!("Drawing circle"); }
}
4.2 Trait Bound 与泛型约束
fn print_drawable<T: Drawable>(item: &T) {
item.draw();
}
// 多约束
fn process<T: Drawable + Clone + Send>(item: T) {}
// where 子句(清晰表达复杂约束)
fn complex<T, U>(t: T, u: U)
where
T: Drawable + Clone,
U: std::fmt::Debug + Send,
{}
4.3 关联类型
trait Iterator {
type Item; // 关联类型
fn next(&mut self) -> Option<Self::Item>;
}
struct Counter;
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> { Some(1) }
}
4.4 Trait Object(动态分发)
fn draw_all(items: &[Box<dyn Drawable>]) {
for item in items { item.draw(); }
}
// dyn Trait 是 unsized,必须用指针包装(Box/Rc/&)
4.5 常用标准 Trait
| Trait | 用途 |
|---|---|
Clone | 深拷贝 |
Copy | 按位复制(move → copy) |
Debug | {:?} 格式化输出 |
Display | {} 格式化输出 |
Default | 默认值构造 |
PartialEq / Eq | 相等比较 |
PartialOrd / Ord | 排序比较 |
Hash | 哈希值计算 |
Send | 可跨线程传递所有权 |
Sync | 可多线程同时引用 |
#[derive(Debug, Clone, PartialEq, Default)]
struct Point { x: f64, y: f64 }
5. 泛型与零成本抽象
5.1 泛型函数与结构体
struct Stack<T> {
items: Vec<T>,
}
impl<T> Stack<T> {
fn new() -> Self { Stack { items: Vec::new() } }
fn push(&mut self, item: T) { self.items.push(item); }
fn pop(&mut self) -> Option<T> { self.items.pop() }
}
5.2 常量泛型(Const Generics)
struct Matrix<T, const N: usize, const M: usize> {
data: [[T; M]; N],
}
let m: Matrix<f64, 3, 3> = Matrix { data: [[0.0; 3]; 3] };
5.3 零成本抽象
Rust 的泛型通过**单态化(Monomorphization)**在编译期展开为具体类型,无运行时开销:
fn max<T: PartialOrd>(a: T, b: T) -> T {
if a > b { a } else { b }
}
// 编译后生成:
// fn max_i32(a: i32, b: i32) -> i32 { ... }
// fn max_f64(a: f64, b: f64) -> f64 { ... }
6. 宏系统
宏在编译期展开,分为声明宏和过程宏。
6.1 声明宏(macro_rules!)
macro_rules! vec_str {
($($x:expr),*) => {
{
let mut temp_vec = Vec::new();
$(temp_vec.push($x.to_string());)*
temp_vec
}
};
}
let v = vec_str!["hello", "world"];
6.2 过程宏(Procedural Macros)
三种类型,需要单独 crate:
// derive 宏(#[derive(MyTrait)])
#[proc_macro_derive(MyTrait)]
pub fn my_trait_derive(input: TokenStream) -> TokenStream { ... }
// 属性宏(#[my_attribute])
#[proc_macro_attribute]
pub fn my_attribute(args: TokenStream, input: TokenStream) -> TokenStream { ... }
// 函数式宏(my_macro!())
#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream { ... }
常用 derive 宏 crate:
serde::Serialize/Deserialize— 序列化derive_builder::Builder— Builder 模式thiserror::Error/anyhow::Error— 错误类型strum::EnumString/Display— 枚举工具
7. Cargo 与 crates 生态
7.1 工作区(Workspace)
# Cargo.toml(根)
[workspace]
members = ["api", "core", "cli"]
resolver = "2"
[workspace.dependencies]
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
7.2 Feature Flags
[features]
default = ["serde"]
serde = ["dep:serde"]
async = ["tokio", "futures"]
#[cfg(feature = "serde")]
impl serde::Serialize for MyType { ... }
7.3 顶级 crates 速查
| 领域 | 推荐 crate |
|---|---|
| 异步运行时 | tokio |
| HTTP 服务端 | axum, actix-web |
| HTTP 客户端 | reqwest |
| 序列化 | serde + serde_json |
| 数据库 | sqlx, diesel, sea-orm |
| CLI | clap, dialoguer |
| 错误处理 | thiserror, anyhow |
| 日志 | tracing, log |
| 测试 | tokio-test, mockall |
| WASM | wasm-bindgen, wasm-pack |
7.4 Cargo 子命令别名
cargo add tokio --features full # 添加依赖
cargo tree # 查看依赖树
cargo audit # 安全审计
cargo clippy -- -D warnings # 静态分析
cargo test --lib # 仅运行单元测试
8. 总结
Rust 的核心概念相互关联形成一个严密的系统:
| 概念 | 解决的问题 | 关键机制 |
|---|---|---|
| 所有权 | 内存泄漏、double-free | move/Clone/Drop |
| 借用 | 悬垂指针、数据竞争 | &T / &mut T,编译期检查 |
| 生命周期 | 引用失效 | ‘a 标注,elision 规则 |
| Trait | 代码复用、多态 | static/dyn 分发 |
| 泛型 | 类型安全 + 零成本 | Monomorphization |
| 宏 | DRY、元编程 | macro_rules! / proc_macro |
掌握这些概念后,可以编写出既安全又高效的系统级代码,同时享受现代语言的抽象能力。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。
「rust」更多文章
Rust 错误处理与测试:thiserror、mockall 与属性测试
Rust 错误处理最佳实践:Result/Option 组合子、thiserror 与 anyhow 选型、panic 边界控制、单元/集成/文档测试、mockall 模拟、property-based testing 与代码覆盖率。
Rust 系统编程与性能优化:零拷贝、内存剖析与编译调优
Rust 系统编程深度实践:操作系统原语、零拷贝 I/O、mmap 内存映射、性能剖析(cargo flamegraph)、编译器优化(LTO/PGO)、Benchmark 与内存分析,以及 no_std 嵌入式场景。
Rust 桌面端与 WASM:Tauri、WebAssembly 与嵌入式开发
Rust 跨平台开发全景:Tauri 替代 Electron 的轻量级架构、WASM 编译(wasm-bindgen/wasm-pack)、WASI 运行时、嵌入式 Rust(no_std/embedded-hal),以及跨平台发布策略。