Blog Home
Updated: 2025 Nov 04

Rust 完全教程

核心理念

Rust 三大支柱:

  • 所有权 (Ownership): 内存安全无 GC
  • 零成本抽象: 高层抽象无运行时开销
  • 并发安全: 编译期消除数据竞争

设计哲学: "如果编译通过,就不会崩溃"

环境配置

安装

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup update  # 更新到最新版本

常用工具

  • rustc: 编译器
  • cargo: 包管理器与构建工具
  • rustfmt: 代码格式化
  • clippy: Lint 工具
  • rust-analyzer: LSP 服务器
cargo new project_name      # 创建项目
cargo build                 # 构建
cargo run                   # 运行
cargo test                  # 测试
cargo doc --open            # 生成文档
cargo clippy                # 代码检查

基础语法

变量与可变性

// 默认不可变
let x = 5;
// x = 6;  // 错误!

// 显式声明可变
let mut y = 5;
y = 6;  // OK

// 常量: 必须标注类型,编译时求值
const MAX_POINTS: u32 = 100_000;

// 遮蔽 (shadowing): 可改变类型
let spaces = "   ";
let spaces = spaces.len();

Tips: 优先使用不可变,需要时才用 mut

数据类型

标量类型

// 整数: i8/u8, i16/u16, i32/u32, i64/u64, i128/u128, isize/usize
let a: i32 = 42;
let b = 0xff;        // 十六进制
let c = 1_000_000;   // 下划线分隔

// 浮点: f32, f64 (默认)
let f = 2.0;  // f64

// 布尔
let t = true;

// 字符: Unicode 标量值
let emoji = '😀';

复合类型

// 元组: 固定长度,类型可不同
let tup: (i32, f64, u8) = (500, 6.4, 1);
let (x, y, z) = tup;  // 解构
let first = tup.0;    // 索引访问

// 数组: 固定长度,类型相同
let arr = [1, 2, 3, 4, 5];
let arr: [i32; 5] = [1, 2, 3, 4, 5];
let arr = [3; 5];  // [3, 3, 3, 3, 3]

函数

// 参数必须标注类型
fn add(x: i32, y: i32) -> i32 {
    x + y  // 表达式,无分号
}

// 语句 vs 表达式
fn example() -> i32 {
    let x = 5;  // 语句
    x + 1       // 表达式,作为返回值
}

// 发散函数
fn diverges() -> ! {
    panic!("This function never returns");
}

控制流

// if 表达式
let number = if condition { 5 } else { 6 };

// loop 无限循环
let result = loop {
    counter += 1;
    if counter == 10 {
        break counter * 2;  // break 可返回值
    }
};

// while 条件循环
while number != 0 {
    number -= 1;
}

// for 迭代
for element in array.iter() {
    println!("{}", element);
}

for number in (1..4).rev() {  // 范围反转
    println!("{}", number);
}

所有权系统

核心规则

  1. 每个值有一个*所有者*
  2. 同时只能有*一个*所有者
  3. 所有者离开作用域,值被丢弃
{
    let s = String::from("hello");  // s 有效
    // 使用 s
}  // s 离开作用域,内存被释放

移动 (Move)

let s1 = String::from("hello");
let s2 = s1;  // s1 的值移动到 s2,s1 失效

// println!("{}", s1);  // 错误! s1 已失效

// 对于栈上数据(实现了 Copy trait),是复制
let x = 5;
let y = x;  // x 仍有效

设计思路: 防止二次释放 (double free)

借用 (Borrowing)

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);  // 借用,不转移所有权
    println!("'{}' length is {}", s1, len);  // s1 仍有效
}

fn calculate_length(s: &String) -> usize {
    s.len()
}  // s 离开作用域,但不拥有数据,所以不释放

可变借用

fn main() {
    let mut s = String::from("hello");
    change(&mut s);
}

fn change(s: &mut String) {
    s.push_str(", world");
}

关键限制:

  • 同一时间,*要么*多个不可变借用,*要么*一个可变借用
  • 借用必须总是有效(引用生命周期)
let mut s = String::from("hello");

let r1 = &s;
let r2 = &s;
// let r3 = &mut s;  // 错误! 已有不可变借用

println!("{} {}", r1, r2);
// r1, r2 作用域结束

let r3 = &mut s;  // OK

Slice

let s = String::from("hello world");

let hello = &s[0..5];   // 字符串 slice
let world = &s[6..11];
let slice = &s[..];     // 整个字符串

// 函数签名使用 &str (字符串 slice)
fn first_word(s: &str) -> &str {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}

// 数组 slice
let a = [1, 2, 3, 4, 5];
let slice = &a[1..3];  // 类型: &[i32]

结构体与枚举

结构体

// 经典结构体
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

let mut user1 = User {
    email: String::from("user@example.com"),
    username: String::from("user123"),
    active: true,
    sign_in_count: 1,
};

user1.email = String::from("new@example.com");

// 字段初始化简写
fn build_user(email: String, username: String) -> User {
    User {
        email,
        username,
        active: true,
        sign_in_count: 1,
    }
}

// 结构体更新语法
let user2 = User {
    email: String::from("another@example.com"),
    ..user1  // 其余字段从 user1 复制/移动
};

// 元组结构体
struct Color(i32, i32, i32);
let black = Color(0, 0, 0);

// 单元结构体
struct AlwaysEqual;

方法

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 方法: 第一个参数是 self
    fn area(&self) -> u32 {
        self.width * self.height
    }

    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }

    // 关联函数: 不以 self 为参数(类似静态方法)
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
}

let rect = Rectangle { width: 30, height: 50 };
println!("Area: {}", rect.area());

let sq = Rectangle::square(25);

枚举

// 基本枚举
enum IpAddrKind {
    V4,
    V6,
}

// 枚举变体携带数据
enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}

let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));

// 复杂枚举
enum Message {
    Quit,                       // 无数据
    Move { x: i32, y: i32 },   // 匿名结构体
    Write(String),              // 单个字符串
    ChangeColor(i32, i32, i32), // 三个整数
}

impl Message {
    fn call(&self) {
        // 方法体
    }
}

Option<T>

// Rust 无 null,使用 Option 表达"可能无值"
enum Option<T> {
    Some(T),
    None,
}

let some_number = Some(5);
let some_string = Some("a string");
let absent_number: Option<i32> = None;

// 必须处理 None 情况才能使用值
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        Some(i) => Some(i + 1),
        None => None,
    }
}

match 模式匹配

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => {
            println!("Lucky penny!");
            1
        }
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter(state) => {
            println!("State quarter from {:?}!", state);
            25
        }
    }
}

// match 必须穷尽所有可能
let dice_roll = 9;
match dice_roll {
    3 => add_fancy_hat(),
    7 => remove_fancy_hat(),
    _ => reroll(),  // 通配符
}

// if let: 只关心一种情况
let some_value = Some(3);
if let Some(3) = some_value {
    println!("three");
}

泛型、Trait 与生命周期

泛型

// 函数泛型
fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in list {
        if item > largest {
            largest = item;
        }
    }
    largest
}

// 结构体泛型
struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

// 为特定类型实现方法
impl Point<f32> {
    fn distance_from_origin(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

// 多个泛型参数
struct Point2<T, U> {
    x: T,
    y: U,
}

// 枚举泛型
enum Result<T, E> {
    Ok(T),
    Err(E),
}

零成本抽象: 泛型在编译时单态化,无运行时开销

Trait

// 定义 trait
pub trait Summary {
    fn summarize(&self) -> String;

    // 默认实现
    fn summarize_author(&self) -> String {
        String::from("(Read more...)")
    }
}

// 为类型实现 trait
pub struct NewsArticle {
    pub headline: String,
    pub content: String,
}

impl Summary for NewsArticle {
    fn summarize(&self) -> String {
        format!("{}: {}", self.headline, self.content)
    }
}

// trait 作为参数
pub fn notify(item: &impl Summary) {
    println!("Breaking news! {}", item.summarize());
}

// trait bound 语法
pub fn notify<T: Summary>(item: &T) {
    println!("Breaking news! {}", item.summarize());
}

// 多个 trait bound
pub fn notify<T: Summary + Display>(item: &T) {}

// where 子句(可读性更好)
fn some_function<T, U>(t: &T, u: &U) -> i32
where
    T: Display + Clone,
    U: Clone + Debug,
{
    // ...
}

// 返回实现 trait 的类型
fn returns_summarizable() -> impl Summary {
    NewsArticle {
        headline: String::from("Title"),
        content: String::from("Content"),
    }
}

常用 Trait

// Clone: 深拷贝
#[derive(Clone)]
struct MyStruct;

// Copy: 栈上按位复制(隐含 Clone)
#[derive(Copy, Clone)]
struct Point { x: i32, y: i32 }

// Debug: 格式化输出
#[derive(Debug)]
struct Rectangle { width: u32, height: u32 }

// PartialEq/Eq: 相等比较
#[derive(PartialEq, Eq)]
struct Person { name: String }

// PartialOrd/Ord: 排序比较
#[derive(PartialOrd, Ord, PartialEq, Eq)]
struct Priority(i32);

// Default: 默认值
#[derive(Default)]
struct Config { timeout: u32 }

// From/Into: 类型转换
impl From<i32> for Number {
    fn from(item: i32) -> Self {
        Number { value: item }
    }
}

// Iterator: 迭代器
struct Counter { count: u32 }

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;
        if self.count < 6 {
            Some(self.count)
        } else {
            None
        }
    }
}

生命周期

// 生命周期注解: 描述引用之间的关系
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

// 结构体中的生命周期
struct ImportantExcerpt<'a> {
    part: &'a str,
}

impl<'a> ImportantExcerpt<'a> {
    fn level(&self) -> i32 {
        3
    }

    // 生命周期省略规则
    fn announce_and_return_part(&self, announcement: &str) -> &str {
        println!("Attention please: {}", announcement);
        self.part
    }
}

// 静态生命周期: 存活于整个程序
let s: &'static str = "I have a static lifetime.";

生命周期省略规则:

  1. 每个引用参数获得独立生命周期
  2. 若只有一个输入生命周期,赋给所有输出
  3. 若多个输入且其中一个是 &self,其生命周期赋给所有输出

错误处理

panic!

// 不可恢复错误
panic!("crash and burn");

// RUST_BACKTRACE=1 获取回溯

Result<T, E>

use std::fs::File;
use std::io::{self, Read};

// 基本处理
fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("username.txt")?;  // ? 操作符传播错误
    let mut s = String::new();
    f.read_to_string(&mut s)?;
    Ok(s)
}

// ? 操作符等价于:
let mut f = match File::open("username.txt") {
    Ok(file) => file,
    Err(e) => return Err(e),
};

// 链式调用
fn read_username_from_file() -> Result<String, io::Error> {
    let mut s = String::new();
    File::open("username.txt")?.read_to_string(&mut s)?;
    Ok(s)
}

// main 也可返回 Result
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let f = File::open("hello.txt")?;
    Ok(())
}

// 自定义错误类型
use std::fmt;

#[derive(Debug)]
struct MyError {
    details: String,
}

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.details)
    }
}

impl std::error::Error for MyError {}

Tips:

  • unwrap(): 遇错 panic
  • expect("msg"): 带消息的 unwrap
  • 生产代码使用 ?match

集合类型

Vec<T>

// 创建
let v: Vec<i32> = Vec::new();
let v = vec![1, 2, 3];  // 宏

// 更新
let mut v = Vec::new();
v.push(5);
v.push(6);

// 访问
let third: &i32 = &v[2];           // 越界会 panic
let third: Option<&i32> = v.get(2); // 返回 Option

// 遍历
for i in &v {
    println!("{}", i);
}

for i in &mut v {
    *i += 50;  // 解引用修改
}

// 存储多种类型(用枚举)
enum SpreadsheetCell {
    Int(i32),
    Float(f64),
    Text(String),
}

let row = vec![
    SpreadsheetCell::Int(3),
    SpreadsheetCell::Text(String::from("blue")),
    SpreadsheetCell::Float(10.12),
];

String

// 创建
let mut s = String::new();
let s = "initial contents".to_string();
let s = String::from("initial contents");

// 更新
s.push_str("bar");
s.push('!');

let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2;  // s1 被移动,不能再使用

// format! 宏(不取得所有权)
let s = format!("{}-{}-{}", s1, s2, s3);

// 索引: Rust 不支持字符串索引!
let s = String::from("hello");
// let h = s[0];  // 错误!

// 原因: UTF-8 编码,字节≠字符
let hello = "Здравствуйте";
let s = &hello[0..4];  // Зд (每个字符2字节)

// 遍历
for c in "नमस्ते".chars() {
    println!("{}", c);
}

for b in "नमस्ते".bytes() {
    println!("{}", b);
}

HashMap<K, V>

use std::collections::HashMap;

// 创建
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

// 从元组 Vec 构建
let teams = vec![String::from("Blue"), String::from("Yellow")];
let initial_scores = vec![10, 50];
let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();

// 访问
let team_name = String::from("Blue");
let score = scores.get(&team_name);  // Option<&V>

// 遍历
for (key, value) in &scores {
    println!("{}: {}", key, value);
}

// 更新
scores.insert(String::from("Blue"), 25);  // 覆盖

// 只在键不存在时插入
scores.entry(String::from("Yellow")).or_insert(50);

// 基于旧值更新
let text = "hello world wonderful world";
let mut map = HashMap::new();

for word in text.split_whitespace() {
    let count = map.entry(word).or_insert(0);
    *count += 1;
}

闭包与迭代器

闭包

// 基本语法
let add_one = |x: i32| x + 1;
let add_one = |x| x + 1;  // 类型推断

// 多行闭包
let expensive_closure = |num| {
    println!("calculating slowly...");
    thread::sleep(Duration::from_secs(2));
    num
};

// 捕获环境
let x = 4;
let equal_to_x = |z| z == x;  // 捕获 x

// 三种捕获方式
// 1. FnOnce: 获取所有权
// 2. FnMut: 可变借用
// 3. Fn: 不可变借用

let mut list = vec![1, 2, 3];
let mut borrows_mutably = || list.push(7);  // FnMut
borrows_mutably();

// move 关键字: 强制取得所有权
let x = vec![1, 2, 3];
let equal_to_x = move |z| z == x;
// println!("{:?}", x);  // 错误! x 已移动

// 作为参数
fn apply<F>(f: F, x: i32) -> i32
where
    F: Fn(i32) -> i32,
{
    f(x)
}

let result = apply(|x| x * 2, 5);

迭代器

let v1 = vec![1, 2, 3];

// 创建迭代器
let v1_iter = v1.iter();       // 不可变引用
let v1_iter = v1.iter_mut();   // 可变引用
let v1_iter = v1.into_iter();  // 获取所有权

// 消耗适配器: 消耗迭代器
let total: i32 = v1.iter().sum();

// 迭代器适配器: 产生新迭代器
let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();

// 链式调用
let v1 = vec![1, 2, 3];
let v2: Vec<_> = v1
    .iter()
    .filter(|x| *x % 2 == 0)
    .map(|x| x * 2)
    .collect();

// 自定义迭代器
struct Counter {
    count: u32,
}

impl Counter {
    fn new() -> Counter {
        Counter { count: 0 }
    }
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        if self.count < 5 {
            self.count += 1;
            Some(self.count)
        } else {
            None
        }
    }
}

// 使用
let sum: u32 = Counter::new()
    .zip(Counter::new().skip(1))
    .map(|(a, b)| a * b)
    .filter(|x| x % 3 == 0)
    .sum();

性能: 迭代器是零成本抽象,编译后与手写循环一样快

智能指针

Box<T>

// 堆分配
let b = Box::new(5);
println!("b = {}", b);

// 递归类型
enum List {
    Cons(i32, Box<List>),
    Nil,
}

use List::{Cons, Nil};

let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));

// 实现 Deref
use std::ops::Deref;

struct MyBox<T>(T);

impl<T> MyBox<T> {
    fn new(x: T) -> MyBox<T> {
        MyBox(x)
    }
}

impl<T> Deref for MyBox<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

let x = 5;
let y = MyBox::new(x);
assert_eq!(5, *y);  // 解引用强制转换

Rc<T>

use std::rc::Rc;

// 引用计数: 多个所有者
enum List {
    Cons(i32, Rc<List>),
    Nil,
}

use List::{Cons, Nil};

let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
println!("count after creating a = {}", Rc::strong_count(&a));

let b = Cons(3, Rc::clone(&a));  // 增加引用计数
let c = Cons(4, Rc::clone(&a));

println!("count after creating c = {}", Rc::strong_count(&a));

注意: Rc<T> 仅用于单线程

RefCell<T>

use std::cell::RefCell;

// 内部可变性: 运行时检查借用规则
let x = RefCell::new(5);

*x.borrow_mut() += 1;  // 可变借用
println!("{}", x.borrow());  // 不可变借用

// 组合 Rc<RefCell<T>>: 多个可变所有者
#[derive(Debug)]
enum List {
    Cons(Rc<RefCell<i32>>, Rc<List>),
    Nil,
}

let value = Rc::new(RefCell::new(5));
let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));

*value.borrow_mut() += 10;  // 修改共享值

循环引用与 Weak<T>

use std::rc::{Rc, Weak};
use std::cell::RefCell;

#[derive(Debug)]
struct Node {
    value: i32,
    parent: RefCell<Weak<Node>>,
    children: RefCell<Vec<Rc<Node>>>,
}

let leaf = Rc::new(Node {
    value: 3,
    parent: RefCell::new(Weak::new()),
    children: RefCell::new(vec![]),
});

let branch = Rc::new(Node {
    value: 5,
    parent: RefCell::new(Weak::new()),
    children: RefCell::new(vec![Rc::clone(&leaf)]),
});

*leaf.parent.borrow_mut() = Rc::downgrade(&branch);

// Weak 不增加强引用计数,防止循环引用

并发编程

线程

use std::thread;
use std::time::Duration;

// 创建线程
let handle = thread::spawn(|| {
    for i in 1..10 {
        println!("hi number {} from spawned thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
});

handle.join().unwrap();  // 等待线程结束

// move 捕获环境
let v = vec![1, 2, 3];
let handle = thread::spawn(move || {
    println!("Here's a vector: {:?}", v);
});
handle.join().unwrap();

消息传递

use std::sync::mpsc;  // multiple producer, single consumer
use std::thread;

// 创建通道
let (tx, rx) = mpsc::channel();

thread::spawn(move || {
    let val = String::from("hi");
    tx.send(val).unwrap();
    // println!("{}", val);  // 错误! val 已移动
});

let received = rx.recv().unwrap();  // 阻塞等待
println!("Got: {}", received);

// 多个发送者
let (tx, rx) = mpsc::channel();
let tx1 = tx.clone();

thread::spawn(move || {
    let vals = vec![
        String::from("hi"),
        String::from("from"),
        String::from("the"),
        String::from("thread"),
    ];
    for val in vals {
        tx.send(val).unwrap();
        thread::sleep(Duration::from_secs(1));
    }
});

thread::spawn(move || {
    let vals = vec![
        String::from("more"),
        String::from("messages"),
    ];
    for val in vals {
        tx1.send(val).unwrap();
        thread::sleep(Duration::from_secs(1));
    }
});

// rx 作为迭代器
for received in rx {
    println!("Got: {}", received);
}

共享状态

use std::sync::{Arc, Mutex};
use std::thread;

// Mutex: 互斥锁
let m = Mutex::new(5);

{
    let mut num = m.lock().unwrap();
    *num = 6;
}  // 锁自动释放

// Arc: 原子引用计数(线程安全的 Rc)
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];

for _ in 0..10 {
    let counter = Arc::clone(&counter);
    let handle = thread::spawn(move || {
        let mut num = counter.lock().unwrap();
        *num += 1;
    });
    handles.push(handle);
}

for handle in handles {
    handle.join().unwrap();
}

println!("Result: {}", *counter.lock().unwrap());

Send 与 Sync

// Send: 可在线程间转移所有权
// Sync: 可从多线程安全访问

// 大多数类型是 Send + Sync
// Rc<T>: 不是 Send 或 Sync
// RefCell<T>: 不是 Sync
// Arc<T>: Send + Sync
// Mutex<T>: Send + Sync

// 手动实现 Send/Sync 是 unsafe 的
unsafe impl Send for MyType {}

异步编程

async/await

use tokio;  // 需要在 Cargo.toml 添加依赖

// async 函数返回 Future
async fn hello_world() {
    println!("hello, world!");
}

// await 等待 Future 完成
async fn learn_song() -> String {
    // 模拟异步操作
    String::from("learned!")
}

async fn sing_song(song: String) {
    println!("Singing: {}", song);
}

async fn learn_and_sing() {
    let song = learn_song().await;
    sing_song(song).await;
}

// 运行时
#[tokio::main]
async fn main() {
    learn_and_sing().await;
}

并发执行

use tokio;

async fn task1() {
    println!("Task 1");
}

async fn task2() {
    println!("Task 2");
}

#[tokio::main]
async fn main() {
    // 并发执行
    let (result1, result2) = tokio::join!(task1(), task2());

    // 或使用 select! (竞争,第一个完成)
    tokio::select! {
        _ = task1() => println!("Task 1 finished first"),
        _ = task2() => println!("Task 2 finished first"),
    }

    // spawn 任务
    let handle = tokio::spawn(async {
        // 异步工作
    });

    handle.await.unwrap();
}

Future trait

use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

struct MyFuture;

impl Future for MyFuture {
    type Output = i32;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        // 模拟工作
        Poll::Ready(42)
    }
}

模式匹配

基础模式

// 匹配字面值
let x = 1;
match x {
    1 => println!("one"),
    2 => println!("two"),
    _ => println!("anything"),
}

// 匹配命名变量
let x = Some(5);
let y = 10;

match x {
    Some(50) => println!("Got 50"),
    Some(y) => println!("Matched, y = {:?}", y),  // 遮蔽外部 y
    _ => println!("Default case"),
}

// 多个模式
match x {
    1 | 2 => println!("one or two"),
    3 => println!("three"),
    _ => println!("anything"),
}

// 范围匹配
match x {
    1..=5 => println!("one through five"),
    _ => println!("something else"),
}

let c = 'c';
match c {
    'a'..='j' => println!("early ASCII letter"),
    'k'..='z' => println!("late ASCII letter"),
    _ => println!("something else"),
}

解构

// 解构结构体
struct Point {
    x: i32,
    y: i32,
}

let p = Point { x: 0, y: 7 };

match p {
    Point { x, y: 0 } => println!("On the x axis at {}", x),
    Point { x: 0, y } => println!("On the y axis at {}", y),
    Point { x, y } => println!("On neither axis: ({}, {})", x, y),
}

// 解构枚举
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

let msg = Message::ChangeColor(0, 160, 255);

match msg {
    Message::Quit => println!("Quit"),
    Message::Move { x, y } => println!("Move to x:{}, y:{}", x, y),
    Message::Write(text) => println!("Text: {}", text),
    Message::ChangeColor(r, g, b) => println!("RGB({}, {}, {})", r, g, b),
}

// 解构嵌套
enum Color {
    Rgb(i32, i32, i32),
    Hsv(i32, i32, i32),
}

enum Message2 {
    ChangeColor(Color),
}

let msg = Message2::ChangeColor(Color::Hsv(0, 160, 255));

match msg {
    Message2::ChangeColor(Color::Rgb(r, g, b)) => {
        println!("RGB: {}, {}, {}", r, g, b)
    }
    Message2::ChangeColor(Color::Hsv(h, s, v)) => {
        println!("HSV: {}, {}, {}", h, s, v)
    }
}

// 解构引用
let points = vec![
    Point { x: 0, y: 0 },
    Point { x: 1, y: 5 },
];

let sum_of_squares: i32 = points
    .iter()
    .map(|&Point { x, y }| x * x + y * y)
    .sum();

高级模式

// 忽略值
let (x, _, z) = (1, 2, 3);

match some_value {
    Some(_) => println!("got a Some"),
    None => (),
}

// .. 忽略剩余值
struct Point3D {
    x: i32,
    y: i32,
    z: i32,
}

let origin = Point3D { x: 0, y: 0, z: 0 };

match origin {
    Point3D { x, .. } => println!("x is {}", x),
}

// 匹配守卫
let num = Some(4);

match num {
    Some(x) if x < 5 => println!("less than five: {}", x),
    Some(x) => println!("{}", x),
    None => (),
}

// @ 绑定
enum Message3 {
    Hello { id: i32 },
}

let msg = Message3::Hello { id: 5 };

match msg {
    Message3::Hello { id: id_variable @ 3..=7 } => {
        println!("Found an id in range: {}", id_variable)
    }
    Message3::Hello { id: 10..=12 } => {
        println!("Found an id in another range")
    }
    Message3::Hello { id } => {
        println!("Found some other id: {}", id)
    }
}

宏系统

声明宏 (macrorules!)

// 基本宏
macro_rules! say_hello {
    () => {
        println!("Hello!");
    };
}

say_hello!();

// 带参数
macro_rules! create_function {
    ($func_name:ident) => {
        fn $func_name() {
            println!("You called {:?}()", stringify!($func_name));
        }
    };
}

create_function!(foo);
foo();

// 重复模式
macro_rules! vec_of_strings {
    ($($x:expr),*) => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x.to_string());
            )*
            temp_vec
        }
    };
}

let v = vec_of_strings!("hello", "world");

// 指示符:
// - ident: 标识符
// - expr: 表达式
// - ty: 类型
// - pat: 模式
// - stmt: 语句
// - block: 代码块
// - item: 项(函数、结构体等)
// - meta: 属性内容
// - tt: token 树

过程宏

// Cargo.toml:
// [lib]
// proc-macro = true
//
// [dependencies]
// syn = "2.0"
// quote = "1.0"

use proc_macro::TokenStream;
use quote::quote;
use syn;

// 派生宏
#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    impl_hello_macro(&ast)
}

fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
    let name = &ast.ident;
    let gen = quote! {
        impl HelloMacro for #name {
            fn hello_macro() {
                println!("Hello, Macro! My name is {}!", stringify!(#name));
            }
        }
    };
    gen.into()
}

// 使用:
#[derive(HelloMacro)]
struct Pancakes;

Pancakes::hello_macro();

// 属性宏
#[proc_macro_attribute]
pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
    // 实现路由逻辑
}

// 使用: #[route(GET, "/")]

// 函数式宏
#[proc_macro]
pub fn sql(input: TokenStream) -> TokenStream {
    // 实现 SQL DSL
}

// 使用: let query = sql!(SELECT * FROM users);

不安全 Rust

unsafe 关键字

// 五种 unsafe 超能力:
// 1. 解引用裸指针
// 2. 调用 unsafe 函数或方法
// 3. 访问或修改可变静态变量
// 4. 实现 unsafe trait
// 5. 访问 union 的字段

// 裸指针
let mut num = 5;

let r1 = &num as *const i32;      // 不可变裸指针
let r2 = &mut num as *mut i32;    // 可变裸指针

unsafe {
    println!("r1 is: {}", *r1);
    println!("r2 is: {}", *r2);
}

// unsafe 函数
unsafe fn dangerous() {
    // 危险操作
}

unsafe {
    dangerous();
}

// 创建 unsafe 代码的安全抽象
fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
    let len = slice.len();
    let ptr = slice.as_mut_ptr();

    assert!(mid <= len);

    unsafe {
        (
            std::slice::from_raw_parts_mut(ptr, mid),
            std::slice::from_raw_parts_mut(ptr.add(mid), len - mid),
        )
    }
}

// 外部函数接口 (FFI)
extern "C" {
    fn abs(input: i32) -> i32;
}

unsafe {
    println!("Absolute value of -3 according to C: {}", abs(-3));
}

// 从其他语言调用 Rust
#[no_mangle]
pub extern "C" fn call_from_c() {
    println!("Just called a Rust function from C!");
}

// 静态变量
static HELLO_WORLD: &str = "Hello, world!";

static mut COUNTER: u32 = 0;

fn add_to_count(inc: u32) {
    unsafe {
        COUNTER += inc;
    }
}

// unsafe trait
unsafe trait Foo {
    // 方法
}

unsafe impl Foo for i32 {
    // 实现
}

高级特性

关联类型

pub trait Iterator {
    type Item;  // 关联类型

    fn next(&mut self) -> Option<Self::Item>;
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        // 实现
    }
}

// vs 泛型: 关联类型每个类型只能实现一次

运算符重载

use std::ops::Add;

#[derive(Debug, PartialEq)]
struct Point {
    x: i32,
    y: i32,
}

impl Add for Point {
    type Output = Point;

    fn add(self, other: Point) -> Point {
        Point {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}

let p1 = Point { x: 1, y: 0 };
let p2 = Point { x: 2, y: 3 };
let p3 = p1 + p2;

// 其他可重载运算符: Sub, Mul, Div, Rem, 
// Neg, Not, BitAnd, BitOr, BitXor, Shl, Shr,
// Index, IndexMut, Deref, DerefMut

完全限定语法

trait Pilot {
    fn fly(&self);
}

trait Wizard {
    fn fly(&self);
}

struct Human;

impl Pilot for Human {
    fn fly(&self) {
        println!("This is your captain speaking.");
    }
}

impl Wizard for Human {
    fn fly(&self) {
        println!("Up!");
    }
}

impl Human {
    fn fly(&self) {
        println!("*waving arms furiously*");
    }
}

let person = Human;
person.fly();           // 调用 Human::fly
Pilot::fly(&person);    // 调用 Pilot::fly
Wizard::fly(&person);   // 调用 Wizard::fly

// 关联函数的完全限定语法
trait Animal {
    fn baby_name() -> String;
}

struct Dog;

impl Dog {
    fn baby_name() -> String {
        String::from("puppy")
    }
}

impl Animal for Dog {
    fn baby_name() -> String {
        String::from("puppy")
    }
}

println!("{}", Dog::baby_name());                    // "puppy"
println!("{}", <Dog as Animal>::baby_name());        // "puppy"

Supertraits

use std::fmt;

trait OutlinePrint: fmt::Display {
    fn outline_print(&self) {
        let output = self.to_string();
        let len = output.len();
        println!("{}", "*".repeat(len + 4));
        println!("*{}*", " ".repeat(len + 2));
        println!("* {} *", output);
        println!("*{}*", " ".repeat(len + 2));
        println!("{}", "*".repeat(len + 4));
    }
}

// 实现 OutlinePrint 必须先实现 Display

newtype 模式

// 为外部类型实现外部 trait
use std::fmt;

struct Wrapper(Vec<String>);

impl fmt::Display for Wrapper {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}]", self.0.join(", "))
    }
}

let w = Wrapper(vec![String::from("hello"), String::from("world")]);
println!("w = {}", w);

类型别名

type Kilometers = i32;  // 类型别名

let x: i32 = 5;
let y: Kilometers = 5;
println!("{} + {} = {}", x, y, x + y);  // 完全等价

// 减少重复
type Thunk = Box<dyn Fn() + Send + 'static>;

let f: Thunk = Box::new(|| println!("hi"));

// 在 Result 中使用
type Result<T> = std::result::Result<T, std::io::Error>;

Never 类型

// ! 表示永不返回
fn bar() -> ! {
    panic!("This function never returns");
}

// continue 的类型是 !
let guess: u32 = match guess.trim().parse() {
    Ok(num) => num,
    Err(_) => continue,  // ! 类型可强制转换为任何类型
};

动态大小类型 (DST)

// str 是 DST: 编译时不知道大小
let s1: &str = "Hello";  // 必须用引用

// trait 对象是 DST
let v: &dyn ToString = &5;

// Sized trait: 编译时已知大小
fn generic<T>(t: T) {
    // T 默认有 Sized 约束
}

// 等价于:
fn generic<T: Sized>(t: T) {}

// 移除 Sized 约束:
fn generic<T: ?Sized>(t: &T) {
    // T 可以是 DST,但必须用引用
}

测试

单元测试

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }

    #[test]
    fn another() {
        assert!(true);
        assert_ne!(1, 2);
    }

    #[test]
    #[should_panic]
    fn it_panics() {
        panic!("Make this test fail");
    }

    #[test]
    #[should_panic(expected = "less than or equal to 100")]
    fn greater_than_100() {
        Guess::new(200);
    }

    #[test]
    fn it_works_result() -> Result<(), String> {
        if 2 + 2 == 4 {
            Ok(())
        } else {
            Err(String::from("two plus two does not equal four"))
        }
    }

    #[test]
    #[ignore]  // 除非 --ignored,否则跳过
    fn expensive_test() {
        // 耗时测试
    }
}

集成测试

// tests/integration_test.rs
use my_crate;

#[test]
fn it_adds_two() {
    assert_eq!(4, my_crate::add_two(2));
}

// tests/common/mod.rs
pub fn setup() {
    // 测试辅助代码
}

// 运行测试
// cargo test                  # 所有测试
// cargo test test_name        # 特定测试
// cargo test --test integration_test  # 特定集成测试文件
// cargo test -- --test-threads=1      # 串行运行
// cargo test -- --show-output         # 显示成功测试的输出

基准测试 (需 nightly)

#![feature(test)]
extern crate test;

#[cfg(test)]
mod benches {
    use super::*;
    use test::Bencher;

    #[bench]
    fn bench_add_two(b: &mut Bencher) {
        b.iter(|| add_two(2));
    }
}

文档

文档注释

/// 为函数或类型生成文档
///
/// # Examples
///
/// ```
/// let result = my_crate::add_one(5);
/// assert_eq!(result, 6);
/// ```
///
/// # Panics
///
/// 当 x 溢出时 panic
///
/// # Errors
///
/// 返回 Err 当 ...
///
/// # Safety
///
/// 调用者必须确保 ...
pub fn add_one(x: i32) -> i32 {
    x + 1
}

//! 为包含项(模块、crate)生成文档
//! 
//! # 我的 Crate
//! 
//! 这个 crate 提供 ...

// cargo doc --open  # 生成并打开文档

Cargo 高级特性

Cargo.toml 配置

[package]
name = "my_project"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <you@example.com>"]
description = "A short description"
license = "MIT OR Apache-2.0"
repository = "https://github.com/username/repo"
keywords = ["cli", "example"]
categories = ["command-line-utilities"]

[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
rand = "0.8"

[dev-dependencies]
criterion = "0.5"

[build-dependencies]
cc = "1.0"

[profile.release]
opt-level = 3
lto = true           # Link Time Optimization
codegen-units = 1    # 更好的优化,但编译慢

[profile.dev]
opt-level = 0

# Workspace
[workspace]
members = [
    "crate1",
    "crate2",
]

Feature Flags

[features]
default = ["std"]
std = []
serde_support = ["serde", "serde_derive"]

[dependencies]
serde = { version = "1.0", optional = true }
serde_derive = { version = "1.0", optional = true }
#[cfg(feature = "serde_support")]
use serde::{Serialize, Deserialize};

#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct MyStruct {
    data: String,
}

// cargo build --features "serde_support"
// cargo build --all-features
// cargo build --no-default-features

条件编译

#[cfg(target_os = "linux")]
fn platform_specific() {
    println!("Linux!");
}

#[cfg(target_os = "windows")]
fn platform_specific() {
    println!("Windows!");
}

#[cfg(all(unix, target_pointer_width = "64"))]
fn unix_64bit() {}

#[cfg(any(target_os = "linux", target_os = "macos"))]
fn unix_like() {}

#[cfg(not(test))]
fn production_only() {}

最佳实践与 Tips

代码组织

// src/lib.rs
pub mod models;      // src/models.rs 或 src/models/mod.rs
pub mod utils;
pub use models::User;  // 重导出

// src/models.rs
pub struct User {
    pub name: String,
}

// 私有性默认原则
mod my_mod {
    pub struct PublicStruct {
        pub public_field: i32,
        private_field: i32,  // 私有
    }

    impl PublicStruct {
        pub fn new() -> PublicStruct {
            PublicStruct {
                public_field: 0,
                private_field: 0,
            }
        }
    }
}

错误处理最佳实践

use thiserror::Error;  // 推荐使用 thiserror

#[derive(Error, Debug)]
pub enum MyError {
    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),

    #[error("Parse error: {0}")]
    Parse(#[from] std::num::ParseIntError),

    #[error("Custom error: {msg}")]
    Custom { msg: String },
}

pub type Result<T> = std::result::Result<T, MyError>;

// 使用 anyhow 处理应用级错误
use anyhow::{Context, Result};

fn read_config() -> Result<Config> {
    let contents = std::fs::read_to_string("config.toml")
        .context("Failed to read config file")?;

    let config: Config = toml::from_str(&contents)
        .context("Failed to parse config")?;

    Ok(config)
}

性能优化技巧

// 1. 避免不必要的克隆
fn process(data: &str) {  // 用借用而非 String
    // ...
}

// 2. 使用 Cow 延迟克隆
use std::borrow::Cow;

fn process<'a>(input: &'a str) -> Cow<'a, str> {
    if input.contains("special") {
        Cow::Owned(input.replace("special", "normal"))
    } else {
        Cow::Borrowed(input)
    }
}

// 3. 预分配容量
let mut vec = Vec::with_capacity(100);

// 4. 使用迭代器而非循环
let sum: i32 = (1..100)
    .filter(|x| x % 2 == 0)
    .map(|x| x * x)
    .sum();

// 5. 使用 &[T] 而非 &Vec<T>
fn process_items(items: &[Item]) {  // 更通用
    // ...
}

// 6. SmallVec: 小数据栈分配
use smallvec::{SmallVec, smallvec};
let mut vec: SmallVec<[u8; 16]> = smallvec![1, 2, 3];

// 7. 使用 unsafe 优化关键路径(谨慎!)
// 但先用 Cargo.toml profile 优化

常用设计模式

// 1. Newtype 模式
struct UserId(u64);
struct UserName(String);

// 2. Builder 模式
pub struct Config {
    host: String,
    port: u16,
}

pub struct ConfigBuilder {
    host: Option<String>,
    port: Option<u16>,
}

impl ConfigBuilder {
    pub fn new() -> Self {
        Self { host: None, port: None }
    }

    pub fn host(mut self, host: String) -> Self {
        self.host = Some(host);
        self
    }

    pub fn port(mut self, port: u16) -> Self {
        self.port = Some(port);
        self
    }

    pub fn build(self) -> Result<Config, &'static str> {
        Ok(Config {
            host: self.host.ok_or("host required")?,
            port: self.port.unwrap_or(8080),
        })
    }
}

// 使用: derive_builder crate 自动生成

// 3. RAII (资源获取即初始化)
struct File {
    handle: std::fs::File,
}

impl File {
    fn new(path: &str) -> std::io::Result<Self> {
        let handle = std::fs::File::open(path)?;
        Ok(File { handle })
    }
}

impl Drop for File {
    fn drop(&mut self) {
        // 自动清理资源
        println!("Closing file");
    }
}

// 4. 类型状态模式
struct Locked;
struct Unlocked;

struct Door<State> {
    _state: PhantomData<State>,
}

impl Door<Locked> {
    fn new() -> Self {
        Door { _state: PhantomData }
    }

    fn unlock(self) -> Door<Unlocked> {
        Door { _state: PhantomData }
    }
}

impl Door<Unlocked> {
    fn open(&self) {
        println!("Door opened");
    }

    fn lock(self) -> Door<Locked> {
        Door { _state: PhantomData }
    }
}

// 5. 策略模式 (使用 trait objects)
trait CompressionStrategy {
    fn compress(&self, data: &[u8]) -> Vec<u8>;
}

struct GzipCompression;
impl CompressionStrategy for GzipCompression {
    fn compress(&self, data: &[u8]) -> Vec<u8> {
        // gzip 实现
        vec![]
    }
}

struct Compressor {
    strategy: Box<dyn CompressionStrategy>,
}

impl Compressor {
    fn compress(&self, data: &[u8]) -> Vec<u8> {
        self.strategy.compress(data)
    }
}

内存布局优化

// 字段排序影响大小
struct Bad {
    a: u8,   // 1 byte + 7 padding
    b: u64,  // 8 bytes
    c: u8,   // 1 byte + 7 padding
}  // 总共: 24 bytes

struct Good {
    b: u64,  // 8 bytes
    a: u8,   // 1 byte
    c: u8,   // 1 byte + 6 padding
}  // 总共: 16 bytes

// 使用 #[repr(C)] 固定布局
#[repr(C)]
struct CLayout {
    x: u8,
    y: u32,
}

// 使用 #[repr(packed)] 移除 padding (小心对齐!)
#[repr(packed)]
struct Packed {
    x: u8,
    y: u32,
}

常用 Crate 推荐

[dependencies]
# 序列化
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml = "0.8"

# 异步运行时
tokio = { version = "1.0", features = ["full"] }
async-std = "1.12"

# HTTP 客户端
reqwest = { version = "0.11", features = ["json"] }
hyper = "0.14"

# Web 框架
axum = "0.7"
actix-web = "4.4"
rocket = "0.5"

# CLI
clap = { version = "4.0", features = ["derive"] }
structopt = "0.3"

# 错误处理
anyhow = "1.0"
thiserror = "1.0"

# 日志
log = "0.4"
env_logger = "0.11"
tracing = "0.1"

# 测试
proptest = "1.0"    # 属性测试
mockall = "0.12"    # Mock
criterion = "0.5"   # 基准测试

# 数据库
sqlx = { version = "0.7", features = ["runtime-tokio-native-tls", "postgres"] }
diesel = { version = "2.1", features = ["postgres"] }

# 实用工具
itertools = "0.12"
rayon = "1.8"       # 数据并行
once_cell = "1.19"  # 延迟初始化
lazy_static = "1.4"
regex = "1.10"
chrono = "0.4"      # 日期时间
uuid = "1.6"

Clippy 常见建议

// 使用 if let 代替 match
// Bad
match some_option {
    Some(x) => println!("{}", x),
    None => {},
}

// Good
if let Some(x) = some_option {
    println!("{}", x);
}

// 使用 .copied() 或 .cloned()
// Bad
let v: Vec<i32> = vec![1, 2, 3];
let x = v.iter().map(|&x| x).collect::<Vec<_>>();

// Good
let x = v.iter().copied().collect::<Vec<_>>();

// 避免不必要的返回
// Bad
fn add(a: i32, b: i32) -> i32 {
    return a + b;
}

// Good
fn add(a: i32, b: i32) -> i32 {
    a + b
}

// 使用 matches! 宏
// Bad
match value {
    Some(1) | Some(2) => true,
    _ => false,
}

// Good
matches!(value, Some(1) | Some(2))

// 使用 ..= 代替 ...
// Bad (已废弃)
match x {
    0...10 => {},
    _ => {},
}

// Good
match x {
    0..=10 => {},
    _ => {},
}

生命周期技巧

// 1. 生命周期省略
fn first_word(s: &str) -> &str {  // 编译器自动推断
    &s[..1]
}

// 2. 'static 生命周期
const GREETING: &'static str = "Hello";

fn get_static() -> &'static str {
    "static string"
}

// 3. 结构体自引用 (使用 Pin)
use std::pin::Pin;

struct SelfReferential {
    data: String,
    ptr: *const String,
}

// 更好的方式: 使用 rental 或 ouroboros crate

// 4. 高阶生命周期 (HRTB)
fn call_with_ref<F>(f: F)
where
    F: for<'a> Fn(&'a str),
{
    f("hello");
}

并发模式

use std::sync::mpsc;
use std::thread;
use std::sync::{Arc, Mutex};

// 1. 工作线程池
struct ThreadPool {
    workers: Vec<Worker>,
    sender: mpsc::Sender<Job>,
}

type Job = Box<dyn FnOnce() + Send + 'static>;

impl ThreadPool {
    fn new(size: usize) -> ThreadPool {
        let (sender, receiver) = mpsc::channel();
        let receiver = Arc::new(Mutex::new(receiver));

        let mut workers = Vec::with_capacity(size);
        for id in 0..size {
            workers.push(Worker::new(id, Arc::clone(&receiver)));
        }

        ThreadPool { workers, sender }
    }

    fn execute<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static,
    {
        let job = Box::new(f);
        self.sender.send(job).unwrap();
    }
}

struct Worker {
    id: usize,
    thread: thread::JoinHandle<()>,
}

impl Worker {
    fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
        let thread = thread::spawn(move || loop {
            let job = receiver.lock().unwrap().recv().unwrap();
            job();
        });

        Worker { id, thread }
    }
}

// 2. Actor 模式
struct Actor {
    receiver: mpsc::Receiver<Message>,
}

enum Message {
    NewJob(String),
    Terminate,
}

impl Actor {
    fn run(&mut self) {
        while let Ok(msg) = self.receiver.recv() {
            match msg {
                Message::NewJob(job) => self.handle_job(job),
                Message::Terminate => break,
            }
        }
    }

    fn handle_job(&self, job: String) {
        println!("Processing: {}", job);
    }
}

测试技巧

// 1. 表格驱动测试
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_add() {
        let test_cases = vec![
            (1, 2, 3),
            (0, 0, 0),
            (-1, 1, 0),
        ];

        for (a, b, expected) in test_cases {
            assert_eq!(add(a, b), expected);
        }
    }

    // 2. 使用 test fixtures
    struct TestFixture {
        db: Database,
    }

    impl TestFixture {
        fn new() -> Self {
            TestFixture {
                db: Database::new_test(),
            }
        }
    }

    impl Drop for TestFixture {
        fn drop(&mut self) {
            self.db.cleanup();
        }
    }

    #[test]
    fn test_with_fixture() {
        let fixture = TestFixture::new();
        // 测试使用 fixture.db
    }

    // 3. 属性测试
    use proptest::prelude::*;

    proptest! {
        #[test]
        fn test_reverse_reverse(s: String) {
            let reversed: String = s.chars().rev().collect();
            let double_reversed: String = reversed.chars().rev().collect();
            prop_assert_eq!(s, double_reversed);
        }
    }
}

编译时计算

const fn

const fn fibonacci(n: u32) -> u32 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci(n - 1) + fibonacci(n - 2),
    }
}

const FIB_10: u32 = fibonacci(10);  // 编译时计算

// const fn 限制:
// - 不能调用非 const fn
// - 不能有循环 (可用递归)
// - 某些操作受限

常量泛型

// 数组长度泛型化
fn sum_array<const N: usize>(arr: [i32; N]) -> i32 {
    arr.iter().sum()
}

let arr = [1, 2, 3, 4, 5];
let total = sum_array(arr);

// 编译时保证大小
struct Matrix<T, const ROWS: usize, const COLS: usize> {
    data: [[T; COLS]; ROWS],
}

impl<T, const ROWS: usize, const COLS: usize> Matrix<T, ROWS, COLS> {
    fn transpose<const NEW_ROWS: usize, const NEW_COLS: usize>(
        self,
    ) -> Matrix<T, NEW_ROWS, NEW_COLS>
    where
        [(); ROWS]: Sized,
        [(); COLS]: Sized,
    {
        // 实现
        todo!()
    }
}

内联汇编

#![feature(asm)]

use std::arch::asm;

unsafe {
    let mut x: u64 = 10;
    asm!(
        "add {0}, {1}",
        inout(reg) x,
        in(reg) 5,
    );
    println!("Result: {}", x);  // 15
}

// x86_64 示例
#[cfg(target_arch = "x86_64")]
unsafe fn cpuid() -> u32 {
    let mut eax: u32;
    asm!(
        "cpuid",
        inout("eax") 0 => eax,
        out("ebx") _,
        out("ecx") _,
        out("edx") _,
    );
    eax
}

模块化与发布

模块系统最佳实践

// src/lib.rs - 库根
pub mod config;
pub mod error;

pub use config::Config;
pub use error::{Error, Result};

// 预导出常用项
pub mod prelude {
    pub use crate::Config;
    pub use crate::Error;
    pub use crate::Result;
}

// src/config.rs
use crate::error::Result;

#[derive(Debug, Clone)]
pub struct Config {
    // ...
}

impl Config {
    pub fn load() -> Result<Self> {
        // ...
    }
}

// 使用者:
use my_crate::prelude::*;

发布到 crates.io

# 1. 登录
cargo login <your-token>

# 2. 检查包
cargo package

# 3. 发布
cargo publish

# 4. 撤回版本 (不删除,仅标记)
cargo yank --vers 1.0.1

# 5. 取消撤回
cargo yank --vers 1.0.1 --undo

语义化版本

# 主版本.次版本.补丁版本
version = "1.2.3"

# 依赖版本指定
[dependencies]
some_crate = "1.2.3"      # 精确版本
some_crate = "^1.2.3"     # >=1.2.3, <2.0.0 (默认)
some_crate = "~1.2.3"     # >=1.2.3, <1.3.0
some_crate = "1.2.*"      # >=1.2.0, <1.3.0
some_crate = ">=1.2, <1.5"
some_crate = { git = "https://github.com/user/repo" }
some_crate = { path = "../local-crate" }

调试技巧

dbg! 宏

fn factorial(n: u32) -> u32 {
    if dbg!(n <= 1) {
        dbg!(1)
    } else {
        dbg!(n * factorial(n - 1))
    }
}

let result = dbg!(factorial(4));

// 输出:
// [src/main.rs:3] n <= 1 = false
// [src/main.rs:3] n <= 1 = false
// [src/main.rs:3] n <= 1 = false
// [src/main.rs:3] n <= 1 = true
// [src/main.rs:4] 1 = 1
// [src/main.rs:6] n * factorial(n - 1) = 2
// ...

日志

use log::{info, warn, error, debug, trace};

fn main() {
    env_logger::init();

    trace!("Trace message");
    debug!("Debug message");
    info!("Info message");
    warn!("Warning message");
    error!("Error message");
}

// 运行: RUST_LOG=debug cargo run

性能分析

# 使用 perf
cargo build --release
perf record --call-graph=dwarf ./target/release/myapp
perf report

# 使用 flamegraph
cargo install flamegraph
cargo flamegraph

# 使用 valgrind
cargo build
valgrind --tool=callgrind ./target/debug/myapp
kcachegrind callgrind.out.*

跨平台编译

目标平台

# 列出所有目标
rustup target list

# 添加目标
rustup target add x86_64-pc-windows-gnu
rustup target add aarch64-unknown-linux-gnu
rustup target add wasm32-unknown-unknown

# 交叉编译
cargo build --target x86_64-pc-windows-gnu

条件编译示例

#[cfg(target_os = "linux")]
mod linux_specific {
    pub fn platform_name() -> &'static str {
        "Linux"
    }
}

#[cfg(target_os = "windows")]
mod windows_specific {
    pub fn platform_name() -> &'static str {
        "Windows"
    }
}

#[cfg(target_os = "macos")]
mod macos_specific {
    pub fn platform_name() -> &'static str {
        "macOS"
    }
}

#[cfg(target_family = "unix")]
fn unix_only() {
    println!("This is Unix-like");
}

#[cfg(target_pointer_width = "64")]
fn only_64bit() {
    println!("64-bit platform");
}

WebAssembly

基础配置

[dependencies]
wasm-bindgen = "0.2"

[lib]
crate-type = ["cdylib"]
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}

#[wasm_bindgen]
pub struct Counter {
    count: i32,
}

#[wasm_bindgen]
impl Counter {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Counter {
        Counter { count: 0 }
    }

    pub fn increment(&mut self) {
        self.count += 1;
    }

    pub fn get_count(&self) -> i32 {
        self.count
    }
}

// 编译:
// wasm-pack build --target web

嵌入式 Rust

nostd 环境

#![no_std]
#![no_main]

use panic_halt as _;  // panic handler
use cortex_m_rt::entry;

#[entry]
fn main() -> ! {
    // 嵌入式主循环
    loop {
        // ...
    }
}

最后的建议

学习路径

  1. 理解所有权系统
  2. 掌握生命周期
  3. 熟悉 trait 系统
  4. 学习并发模式
  5. 探索异步编程
  6. 深入 unsafe 和 FFI

实践建议

  • 从小项目开始: CLI 工具、API 客户端
  • 阅读优秀 crate 源码: serde, tokio, clap
  • 参与开源项目
  • 善用 Rust 社区: Reddit, Discord, 论坛
  • 坚持"如果编译通过,大概率正确"的信念

资源推荐

常见陷阱

  1. 过度使用 clone()unwrap()
  2. 与借用检查器对抗而非协作
  3. 忽视生命周期注解的含义
  4. 在不需要时使用 Arc<Mutex<T>>
  5. 过早优化

心态调整

Rust 学习曲线陡峭但值得:

  • 初期: 与编译器搏斗
  • 中期: 理解编译器意图
  • 后期: 感激编译器保护

编译器是你的朋友,不是敌人!

Comments:

Email questions, comments, and corrections to hi@smartisan.dev.

Submissions may appear publicly on this website, unless requested otherwise in your email.