第一部分:基础入门

1. 安装与环境配置

Rustup 安装

# Linux/macOS
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh

# Windows: 访问 https://www.rust-lang.org/install.html

验证安装

rustc --version  # 查看编译器版本
cargo --version   # 查看包管理工具版本

更新与卸载

rustup update        # 更新Rust
rustup self uninstall # 卸载Rust
rustup doc           # 打开本地文档

2. Hello World 程序

fn main() {
    println!("Hello, world!");
}

编译与运行

rustc main.rs    # 编译
./main           # 运行(Windows: .\main.exe)

关键点

  • main 函数是程序入口点

  • println! 是宏(macro),注意感叹号

  • Rust源文件以 .rs 结尾

  • 语句以分号 ; 结束

3. Cargo 项目管理

创建项目

cargo new project_name   # 创建新项目
cargo init               # 初始化现有目录

项目结构

my_project/
├── Cargo.toml    # 项目配置文件
├── Cargo.lock    # 依赖锁定文件
└── src/
    └── main.rs   # 源代码

常用命令

cargo build       # 构建项目(debug模式)
cargo build --release  # 发布构建(优化)
cargo run         # 构建并运行
cargo check       # 快速检查是否可编译(不生成可执行文件)
cargo test        # 运行测试
cargo doc --open  # 生成并打开文档

第二部分:核心编程概念

1. 变量与可变性

变量绑定

let x = 5;        // 不可变变量(默认)
let mut y = 5;    // 可变变量
y = 6;            // 可以修改

常量

const MAX_POINTS: u32 = 100_000;  // 必须标注类型,全大写命名

遮蔽(Shadowing)

let x = 5;
let x = x + 1;        // 新变量遮蔽旧变量
{
    let x = x * 2;    // 在内部作用域遮蔽
    println!("{}", x); // 12
}
println!("{}", x);     // 6

2. 数据类型

标量类型

类型 说明 示例
整型 i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize let x: i32 = 42;
浮点型 f32, f64 let x = 2.0; // f64
布尔型 bool let t = true;
字符型 char(4字节,Unicode) let c = '😻';

整型溢出处理

// Debug模式: panic
// Release模式: 二进制补码回绕
let x: u8 = 255;
let y = x.wrapping_add(1);    // 回绕
let z = x.checked_add(1);     // 返回Option
let w = x.saturating_add(1);   // 饱和处理

复合类型

元组(Tuple)

let tup: (i32, f64, u8) = (500, 6.4, 1);
let (x, y, z) = tup;           // 解构
let first = tup.0;              // 索引访问
let unit = ();                  // 单元类型

数组(Array)

let a = [1, 2, 3, 4, 5];       // 固定长度
let b: [i32; 5] = [1, 2, 3, 4, 5];
let c = [3; 5];                // [3, 3, 3, 3, 3]
let first = a[0];               // 索引访问(越界会panic)

3. 函数

函数定义

fn add(x: i32, y: i32) -> i32 {
    x + y    // 隐式返回(无分号)
}

fn early_return(x: i32) -> i32 {
    if x < 0 {
        return 0;  // 提前返回
    }
    x
}

语句与表达式

  • 语句:执行操作但不返回值(如 let x = 5;

  • 表达式:计算并返回值(如 5 + 6,代码块)

let y = {
    let x = 3;
    x + 1    // 表达式,无分号
}; // y = 4

4. 控制流

if 表达式

let number = 6;
if number % 4 == 0 {
    println!("divisible by 4");
} else if number % 3 == 0 {
    println!("divisible by 3");
} else {
    println!("not divisible");
}

// if 作为表达式
let result = if condition { 5 } else { 6 }; // 分支类型必须一致

循环

loop - 无限循环

let mut counter = 0;
let result = loop {
    counter += 1;
    if counter == 10 {
        break counter * 2;  // 返回值
    }
};

while - 条件循环

let mut number = 3;
while number != 0 {
    println!("{}!", number);
    number -= 1;
}

for - 遍历集合

let a = [10, 20, 30, 40, 50];
for element in a {
    println!("{}", element);
}

// 使用Range
for number in (1..4).rev() {
    println!("{}!", number);  // 3! 2! 1!
}

循环标签

'outer: loop {
    loop {
        break 'outer;  // 跳出外层循环
    }
}

第三部分:所有权系统

1. 所有权规则

  1. Rust中每一个值都有一个所有者

  2. 值在任一时刻有且只有一个所有者

  3. 当所有者离开作用域,值被丢弃

栈与堆

  • :LIFO,存储固定大小数据,速度快

  • :存储动态大小数据,速度较慢

2. 移动与克隆

移动(Move)

let s1 = String::from("hello");
let s2 = s1;      // s1被移动到s2,s1不再有效
// println!("{}", s1); // 编译错误

克隆(Clone)

let s1 = String::from("hello");
let s2 = s1.clone();  // 深拷贝
println!("{} {}", s1, s2); // 正常工作

拷贝(Copy)

let x = 5;
let y = x;    // 整型实现Copy,x仍有效

实现 Copy 的类型:

  • 所有整数类型(i32, u64等)

  • 布尔类型 bool

  • 所有浮点类型(f64等)

  • 字符类型 char

  • 元组(仅当所有元素都实现Copy)

3. 引用与借用

不可变引用

fn calculate_length(s: &String) -> usize {
    s.len()
}

let s1 = String::from("hello");
let len = calculate_length(&s1);  // 借用

可变引用

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

let mut s = String::from("hello");
change(&mut s);

引用规则

  1. 任意时刻,只能有一个可变引用多个不可变引用

  2. 引用必须始终有效

let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
// let r3 = &mut s; // 编译错误:不能同时存在不可变和可变引用
println!("{} {}", r1, r2);

4. Slice 类型

字符串Slice

let s = String::from("hello world");
let hello = &s[0..5];   // "hello"
let world = &s[6..11];  // "world"
let slice = &s[..2];    // 从开头到索引2
let slice = &s[3..];    // 从索引3到结尾
let slice = &s[..];     // 整个字符串

函数参数:优先使用 &str

fn first_word(s: &str) -> &str {
    // 可以接受 &String 或 &str
}

第四部分:结构体与枚举

1. 结构体定义与实例化

定义结构体

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

实例化

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

字段初始化简写

fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username,    // 字段名与变量名相同
        email,
        sign_in_count: 1,
    }
}

结构体更新语法

let user2 = User {
    email: String::from("another@example.com"),
    ..user1   // 剩余字段从user1获取(注意:String会被移动)
};

元组结构体

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);

类单元结构体

struct AlwaysEqual;
let subject = AlwaysEqual;

2. 方法语法

定义方法

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

impl Rectangle {
    // 方法:&self借用
    fn area(&self) -> u32 {
        self.width * self.height
    }
    
    // 可变借用
    fn set_width(&mut self, width: u32) {
        self.width = width;
    }
    
    // 获取所有权(少见)
    fn into_string(self) -> String {
        format!("{}x{}", self.width, self.height)
    }
}

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

关联函数

impl Rectangle {
    // 关联函数(不是方法)
    fn square(size: u32) -> Self {
        Self { width: size, height: size }
    }
}

let sq = Rectangle::square(3);

多个impl块

impl Rectangle {
    fn area(&self) -> u32 { /* ... */ }
}

impl Rectangle {
    fn can_hold(&self, other: &Rectangle) -> bool { /* ... */ }
}

3. 枚举

定义枚举

enum IpAddrKind {
    V4,
    V6,
}

// 关联数据
enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}

enum Message {
    Quit,
    Move { x: i32, y: i32 },  // 结构体变体
    Write(String),
    ChangeColor(i32, i32, i32),
}

枚举方法

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

4. Option 枚举

enum Option<T> {
    Some(T),
    None,
}

let some_number = Some(5);
let some_char = Some('e');
let absent_number: Option<i32> = None;

// 不能将Option与普通类型直接运算
let x: i8 = 5;
let y: Option<i8> = Some(5);
// let sum = x + y; // 编译错误

第五部分:模式匹配

1. match 表达式

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

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

匹配 Option

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

匹配必须穷尽

// 编译错误:没有处理None
match x {
    Some(i) => Some(i + 1),
}

通配模式

let dice_roll = 9;
match dice_roll {
    3 => add_fancy_hat(),
    7 => remove_fancy_hat(),
    other => move_player(other),  // 通配变量
    // _ => (),  // 忽略值
}

2. if let 与 let else

// if let - 只关心一种模式
let config_max = Some(3u8);
if let Some(max) = config_max {
    println!("Maximum is {}", max);
}

// if let else
if let Coin::Quarter(state) = coin {
    println!("State quarter from {:?}!", state);
} else {
    count += 1;
}

// let else - 模式匹配失败时提前返回
let Some(value) = optional_value else {
    return None;
};

第六部分:模块系统

1. 包与Crate

  • Crate:编译的最小单元,可以是二进制或库

  • Package:包含Cargo.toml,可包含多个Crate

Crate根文件

  • src/main.rs:二进制crate根

  • src/lib.rs:库crate根

  • src/bin/*.rs:多个二进制crate

2. 模块定义

// src/lib.rs
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
        fn seat_at_table() {}
    }
    
    mod serving {
        fn take_order() {}
    }
}

模块树

crate
 └── front_of_house
     ├── hosting
     │   ├── add_to_waitlist
     │   └── seat_at_table
     └── serving
         ├── take_order
         └── serve_order

3. 路径

// 绝对路径(从crate根开始)
crate::front_of_house::hosting::add_to_waitlist();

// 相对路径
front_of_house::hosting::add_to_waitlist();

// super路径(父模块)
super::deliver_order();

4. pub 关键字

// 模块公有
pub mod hosting {
    // 函数公有
    pub fn add_to_waitlist() {}
}

// 结构体公有但字段私有
pub struct Breakfast {
    pub toast: String,      // 公有字段
    seasonal_fruit: String,  // 私有字段
}

// 枚举公有则所有变体公有
pub enum Appetizer {
    Soup,
    Salad,
}

5. use 关键字

// 导入模块
use crate::front_of_house::hosting;

// 导入函数(习惯:导入父模块)
use crate::front_of_house::hosting::add_to_waitlist;

// 重命名
use std::io::Result as IoResult;

// 重导出
pub use crate::front_of_house::hosting;

// 嵌套路径
use std::{cmp::Ordering, io};
use std::io::{self, Write};

// Glob导入
use std::collections::*;

6. 模块文件拆分

src/
├── lib.rs
├── front_of_house.rs
└── front_of_house/
    └── hosting.rs

// src/lib.rs
mod front_of_house;
pub use crate::front_of_house::hosting;

// src/front_of_house.rs
pub mod hosting;

// src/front_of_house/hosting.rs
pub fn add_to_waitlist() {}

第七部分:常见集合

1. Vector

创建

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

更新

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

读取

let v = vec![1, 2, 3, 4, 5];
let third: &i32 = &v[2];        // 索引(越界panic)
let third: Option<&i32> = v.get(2); // 安全访问

// 遍历
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")),
];

2. 字符串

创建

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

更新

let mut s = String::from("foo");
s.push_str("bar");  // 追加字符串
s.push('l');        // 追加字符

// + 运算符
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2;  // s1被移动

// format! 宏
let s = format!("{}-{}-{}", s1, s2, s3);

索引与遍历

// Rust字符串不支持索引(UTF-8编码)
let hello = "Здравствуйте";
let s = &hello[0..4];  // 按字节切片

// 遍历字符
for c in "Зд".chars() {
    println!("{}", c);
}

// 遍历字节
for b in "Зд".bytes() {
    println!("{}", b);
}

3. HashMap

创建

use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

读取

let team_name = String::from("Blue");
let score = scores.get(&team_name).copied().unwrap_or(0);

// 遍历
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 field_name = String::from("Favorite color");
let field_value = String::from("Blue");
let mut map = HashMap::new();
map.insert(field_name, field_value);
// field_name和field_value不再有效

第八部分:错误处理

1. panic! 不可恢复错误

显式panic

panic!("crash and burn");

调试backtrace

RUST_BACKTRACE=1 cargo run

panic行为配置

[profile.release]
panic = 'abort'  # 使用终止而非展开

2. Result 可恢复错误

Result类型

enum Result<T, E> {
    Ok(T),
    Err(E),
}

处理Result

use std::fs::File;
use std::io::ErrorKind;

let greeting_file_result = File::open("hello.txt");
let greeting_file = match greeting_file_result {
    Ok(file) => file,
    Err(error) => match error.kind() {
        ErrorKind::NotFound => match File::create("hello.txt") {
            Ok(fc) => fc,
            Err(e) => panic!("Problem creating the file: {:?}", e),
        },
        other_error => {
            panic!("Problem opening the file: {:?}", other_error);
        }
    },
};

快捷方法

let file = File::open("hello.txt").unwrap();   // 失败时panic
let file = File::open("hello.txt")
    .expect("Failed to open hello.txt");  // 自定义panic消息

3. 传播错误(? 运算符)

手动传播

fn read_username_from_file() -> Result<String, io::Error> {
    let mut username_file = match File::open("hello.txt") {
        Ok(file) => file,
        Err(e) => return Err(e),
    };
    let mut username = String::new();
    match username_file.read_to_string(&mut username) {
        Ok(_) => Ok(username),
        Err(e) => Err(e),
    }
}

使用 ? 运算符

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

// 更简洁
fn read_username_from_file() -> Result<String, io::Error> {
    fs::read_to_string("hello.txt")
}

? 与 Option

fn last_char_of_first_line(text: &str) -> Option<char> {
    text.lines().next()?.chars().last()
}

main函数返回Result

fn main() -> Result<(), Box<dyn Error>> {
    let file = File::open("hello.txt")?;
    Ok(())
}

4. 何时使用 panic vs Result

  • panic:示例、原型、测试、已知情况不可能失败

  • Result:可能的错误,让调用者决定处理方式

自定义类型验证

pub struct Guess {
    value: i32,
}

impl Guess {
    pub fn new(value: i32) -> Guess {
        if value < 1 || value > 100 {
            panic!("Guess value must be between 1 and 100, got {}.", value);
        }
        Guess { value }
    }
    
    pub fn value(&self) -> i32 {
        self.value
    }
}

第九部分:泛型、Trait与生命周期

1. 泛型

函数定义

fn largest<T>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in list {
        if item > largest {  // 需要T实现PartialOrd
            largest = item;
        }
    }
    largest
}

结构体定义

struct Point<T, U> {
    x: T,
    y: U,
}

let both_integer = Point { x: 5, y: 10 };
let integer_and_float = Point { x: 5, y: 4.0 };

枚举定义

enum Result<T, E> {
    Ok(T),
    Err(E),
}

方法定义

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()
    }
}

泛型性能:单态化(Monomorphization),无运行时开销

2. Trait

定义Trait

pub trait Summary {
    fn summarize(&self) -> String;
}

实现Trait

pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

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

默认实现

pub trait Summary {
    fn summarize(&self) -> String {
        String::from("(Read more...)")
    }
}

pub trait Summary {
    fn summarize_author(&self) -> String;
    fn summarize(&self) -> String {
        format!("(Read more from {}...)", self.summarize_author())
    }
}

Trait作为参数

// impl 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
pub fn notify(item: &(impl Summary + Display)) {}
// 或
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 { /* ... */ }
}

有条件实现方法

use std::fmt::Display;

impl<T: Display + PartialOrd> Pair<T> {
    fn cmp_display(&self) {
        if self.x >= self.y {
            println!("The largest member is x = {}", self.x);
        } else {
            println!("The largest member is y = {}", self.y);
        }
    }
}

3. 生命周期

生命周期注解语法

&i32        // 引用
&'a i32     // 带有显式生命周期的引用
&'a mut i32 // 带有显式生命周期的可变引用

函数签名中的生命周期

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,
}

生命周期省略规则

  1. 每个引用参数都有自己的生命周期参数

  2. 如果只有一个输入生命周期,输出生命周期与其相同

  3. 如果有 &self 或 &mut self,输出生命周期为self的生命周期

静态生命周期

let s: &'static str = "I have a static lifetime.";

结合泛型、Trait和生命周期

use std::fmt::Display;

fn longest_with_an_announcement<'a, T>(
    x: &'a str,
    y: &'a str,
    ann: T,
) -> &'a str
where
    T: Display,
{
    println!("Announcement! {}", ann);
    if x.len() > y.len() { x } else { y }
}

第十部分:智能指针

1. Box<T>

用途:堆上分配、递归类型、trait对象

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

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

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

2. Deref Trait

实现Deref

use std::ops::Deref;

struct MyBox<T>(T);

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);  // 解引用

Deref强制转换

fn hello(name: &str) {
    println!("Hello, {}!", name);
}

let m = MyBox::new(String::from("Rust"));
hello(&m);  // &MyBox<String> -> &String -> &str

3. Drop Trait

struct CustomSmartPointer {
    data: String,
}

impl Drop for CustomSmartPointer {
    fn drop(&mut self) {
        println!("Dropping with data `{}`!", self.data);
    }
}

let c = CustomSmartPointer { data: String::from("my stuff") };
drop(c);  // 手动提前释放

4. Rc<T> - 引用计数

用途:单线程共享所有权

use std::rc::Rc;

enum List {
    Cons(i32, Rc<List>),
    Nil,
}

let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
let b = Cons(3, Rc::clone(&a));
let c = Cons(4, Rc::clone(&a));

// 查看引用计数
println!("count = {}", Rc::strong_count(&a));

5. RefCell<T> - 内部可变性

用途:运行时借用检查

use std::cell::RefCell;

let x = RefCell::new(5);
{
    let mut y = x.borrow_mut();  // 可变借用
    *y += 1;
}
let z = x.borrow();  // 不可变借用
println!("{}", z);

运行时panic

// 违反借用规则会panic
let mut one_borrow = x.borrow_mut();
let mut two_borrow = x.borrow_mut();  // 运行时panic

6. 组合使用

Rc<RefCell<T>>

use std::cell::RefCell;
use std::rc::Rc;

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

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

7. 引用循环与 Weak<T>

引用循环问题

use std::cell::RefCell;
use std::rc::Rc;

#[derive(Debug)]
enum List {
    Cons(i32, RefCell<Rc<List>>),
    Nil,
}

// 可能导致内存泄漏

使用 Weak 打破循环

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

#[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);

// 升级弱引用
let parent = leaf.parent.borrow().upgrade();  // Option<Rc<Node>>

第十一部分:并发

1. 线程

创建线程

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));
    }
});

for i in 1..5 {
    println!("hi number {} from main 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();

2. 消息传递

使用channel

use std::sync::mpsc;
use std::thread;

let (tx, rx) = mpsc::channel();

thread::spawn(move || {
    let val = String::from("hi");
    tx.send(val).unwrap();
});

let received = rx.recv().unwrap();
println!("Got: {}", received);

多生产者

let (tx, rx) = mpsc::channel();
let tx1 = tx.clone();

// 两个线程发送消息
// ...

for received in rx {
    println!("Got: {}", received);
}

3. 共享状态

Mutex

use std::sync::Mutex;

let m = Mutex::new(5);
{
    let mut num = m.lock().unwrap();
    *num = 6;
}
println!("m = {:?}", m);

Arc - 原子引用计数

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

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());

组合选择指南

场景 单线程 多线程
堆分配 Box<T> Box<T>
共享只读 Rc<T> Arc<T>
共享可变 Rc<RefCell<T>> Arc<Mutex<T>> 或 Arc<RwLock<T>>
按值替换 Cell<T> 不适用
防止循环 Weak<T> Weak<T>(配合Arc)

4. Send 与 Sync Trait

  • Send:可在线程间转移所有权

  • Sync:可在线程间安全共享引用

Rc<T> 不是 SendRefCell<T> 不是 Sync

第十二部分:Async 与 Await

1. Future 基础

use trpl::Html;

async fn page_title(url: &str) -> Option<String> {
    let response = trpl::get(url).await;
    let response_text = response.text().await;
    Html::parse(&response_text)
        .select_first("title")
        .map(|title| title.inner_html())
}

Future trait

trait Future {
    type Output;
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

enum Poll<T> {
    Ready(T),
    Pending,
}

2. 运行时

fn main() {
    trpl::run(async {
        let title = page_title("https://example.com").await;
        println!("Title: {:?}", title);
    });
}

3. 并发执行

join

let fut1 = async { /* ... */ };
let fut2 = async { /* ... */ };
let (result1, result2) = trpl::join(fut1, fut2).await;

join! 宏

let (r1, r2, r3) = trpl::join!(fut1, fut2, fut3).await;

join_all

let futures = vec![fut1, fut2, fut3];
let results = trpl::join_all(futures).await;

race

match trpl::race(fut1, fut2).await {
    Either::Left(result) => println!("fut1 won: {}", result),
    Either::Right(result) => println!("fut2 won: {}", result),
}

4. Pin 与 Unpin

  • Pin:防止值在内存中移动

  • Unpin:可安全移动的类型

let pinned = pin!(async { /* ... */ });

5. Stream

创建Stream

use trpl::StreamExt;

let stream = trpl::stream_from_iter(vec![1, 2, 3]);
while let Some(value) = stream.next().await {
    println!("{}", value);
}

Stream操作

let filtered = stream.filter(|x| x % 2 == 0);
let mapped = stream.map(|x| x * 2);
let throttled = stream.throttle(Duration::from_millis(100));
let merged = stream1.merge(stream2);

第十三部分:测试

1. 单元测试

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn exploration() {
        let result = add(2, 2);
        assert_eq!(result, 4);
    }
    
    #[test]
    fn another() {
        panic!("Make this test fail");
    }
}

断言宏

assert!(condition);           // 条件为true时通过
assert_eq!(left, right);       // 相等时通过
assert_ne!(left, right);       // 不相等时通过

// 自定义错误信息
assert!(
    result.contains("Carol"),
    "Greeting did not contain name, value was `{}`",
    result
);

2. 测试 panic

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

3. 使用 Result 的测试

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

4. 控制测试运行

cargo test -- --test-threads=1          # 单线程运行
cargo test -- --show-output             # 显示println输出
cargo test test_name                    # 运行特定测试
cargo test prefix_                      # 运行匹配前缀的测试
cargo test -- --ignored                 # 运行忽略的测试
cargo test -- --include-ignored         # 运行所有测试

5. 集成测试

my_project/
├── src/
│   └── lib.rs
└── tests/
    ├── integration_test.rs
    └── common/
        └── mod.rs

// tests/integration_test.rs
use my_lib::add_two;

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

第十四部分:高级特性

1. 不安全Rust

不安全超能力

  1. 解引用裸指针

  2. 调用不安全函数

  3. 访问/修改可变静态变量

  4. 实现不安全trait

  5. 访问union字段

裸指针

let mut num = 5;
let r1 = &raw const num;
let r2 = &raw mut num;

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

调用不安全函数

unsafe fn dangerous() {}

unsafe {
    dangerous();
}

安全抽象示例

use std::slice;

fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
    let len = values.len();
    let ptr = values.as_mut_ptr();
    assert!(mid <= len);
    
    unsafe {
        (
            slice::from_raw_parts_mut(ptr, mid),
            slice::from_raw_parts_mut(ptr.add(mid), len - mid),
        )
    }
}

2. 高级Trait

关联类型

pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

默认泛型参数

use std::ops::Add;

trait Add<Rhs=Self> {
    type Output;
    fn add(self, rhs: Rhs) -> Self::Output;
}

完全限定语法

// 消除同名方法歧义
Pilot::fly(&person);
Wizard::fly(&person);
<Dog as Animal>::baby_name()

超Trait

trait OutlinePrint: fmt::Display {
    fn outline_print(&self) {
        let output = self.to_string();
        // ...
    }
}

3. 类型别名

type Kilometers = i32;
type Thunk = Box<dyn Fn() + Send + 'static>;

// 类型别名与Result
type Result<T> = std::result::Result<T, std::io::Error>;

4. Never类型

fn bar() -> ! {
    panic!("never returns");
}

5. 动态大小类型

Sized Trait

fn generic<T: ?Sized>(t: &T) {
    // T可以是Sized或非Sized
}

6. 函数指针

fn add_one(x: i32) -> i32 {
    x + 1
}

fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
    f(arg) + f(arg)
}

let answer = do_twice(add_one, 5);

7. 返回闭包

fn returns_closure() -> impl Fn(i32) -> i32 {
    |x| x + 1
}

fn returns_closure_boxed() -> Box<dyn Fn(i32) -> i32> {
    Box::new(|x| x + 1)
}

8. 宏

声明宏

#[macro_export]
macro_rules! vec {
    ( $( $x:expr ),* ) => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
            )*
            temp_vec
        }
    };
}

过程宏 - 自定义derive

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()
}

附录:常用代码片段

文件读写

use std::fs;
use std::io::{self, BufRead, BufReader, Write};

// 读取整个文件
let contents = fs::read_to_string("file.txt")?;

// 读取到字符串(推荐)
fn read_file(path: &str) -> io::Result<String> {
    fs::read_to_string(path)
}

// 按行读取
let file = File::open("file.txt")?;
let reader = BufReader::new(file);
for line in reader.lines() {
    let line = line?;
    println!("{}", line);
}

// 写入文件
fs::write("output.txt", "content")?;

命令行参数

use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        eprintln!("Usage: program <arg>");
        std::process::exit(1);
    }
    let query = &args[1];
    let file_path = &args[2];
}

错误处理模式

// 文件操作
let file = File::open("file.txt")
    .unwrap_or_else(|err| {
        eprintln!("Failed to open file: {}", err);
        std::process::exit(1);
    });

// 传播错误
fn process_data() -> Result<String, io::Error> {
    let content = fs::read_to_string("file.txt")?;
    Ok(content.trim().to_string())
}

// 自定义错误
#[derive(Debug, thiserror::Error)]
pub enum MyError {
    #[error("IO error: {0}")]
    Io(#[from] io::Error),
    #[error("Parse error: {0}")]
    Parse(String),
}

迭代器操作

let numbers = vec![1, 2, 3, 4, 5];

// 常见迭代器方法
numbers.iter().map(|x| x * 2);        // 转换
numbers.iter().filter(|x| x % 2 == 0); // 过滤
numbers.iter().take(3);                // 取前N个
numbers.iter().skip(2);                // 跳过N个
numbers.iter().any(|x| x > 3);         // 任意匹配
numbers.iter().all(|x| x > 0);         // 全部匹配
numbers.iter().find(|x| x == 3);       // 查找
numbers.iter().fold(0, |acc, x| acc + x); // 折叠
numbers.iter().collect::<Vec<_>>();    // 收集

更多推荐