Rust 开发岗位核心面试指南

2 阅读17分钟

Rust 开发岗位核心面试指南(2026 最新版)

本资料涵盖 Rust 后端开发面试的核心知识点,适用于校招/社招准备。

最后更新: 2026 年 3 月 19 日


📑 目录

  1. Rust 基础与所有权
  2. 借用与引用
  3. 生命周期
  4. 智能指针
  5. trait 与泛型
  6. 错误处理
  7. 异步编程与 Tokio
  8. 并发编程
  9. 内存管理与 unsafe
  10. 高频面试题速查

第一部分 Rust 基础与所有权

1.1 Rust 语言特性

核心特性

  • 内存安全:无需垃圾回收,编译期保证
  • 零成本抽象:高级特性无运行时开销
  • 并发安全:所有权系统防止数据竞争
  • 模式匹配:强大的 match 表达式
  • 类型推断:减少显式类型标注

与其他语言对比

特性RustC++GoJava
内存安全编译期保证手动管理GCGC
性能⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
学习曲线陡峭陡峭平缓平缓
并发安全编译期保证运行时保证运行时保证运行时保证

1.2 所有权系统(⭐⭐⭐⭐⭐)

三大规则

1. 每个值都有一个变量,该变量是其所有者
2. 一次只能有一个所有者
3. 当所有者离开作用域时,值将被丢弃(drop)

所有权转移(Move)

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;  // 所有权转移,s1 不再有效
    
    // println!("{}", s1);  // ❌ 编译错误:value borrowed here after move
    println!("{}", s2);    // ✅ 正确
}

// 栈上数据 vs 堆上数据
let x = 5;
let y = x;  // ✅ 拷贝,i32 实现 Copy trait

let s1 = String::from("hello");
let s2 = s1;  // 转移,String 不实现 Copy

Drop trait

struct MyResource {
    data: Vec<u8>,
}

impl Drop for MyResource {
    fn drop(&mut self) {
        println!("资源被释放");
        // 自定义清理逻辑
    }
}

fn main() {
    let resource = MyResource { data: vec![1, 2, 3] };
    // 离开作用域时自动调用 drop
}

提前释放

fn main() {
    let s = String::from("hello");
    // 使用 s
    drop(s);  // 显式提前释放
    // s 不能再使用
}

1.3 变量与可变性

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

// 可变变量
let mut y = 5;
y = 6;  // ✅ 正确

// 常量(必须标注类型)
const MAX_POINTS: u32 = 100_000;

// shadowing(遮蔽)
let x = 5;
let x = x + 1;  // ✅ 新变量,遮蔽旧变量
let x = x * 2;  // x = 12

// shadowing vs mut
let mut s = String::from("hello");
s = String::from("world");  // 重新赋值

let s = String::from("hello");
let s = String::from("world");  // shadowing,类型可以不同

1.4 数据类型

标量类型

类型说明示例
i32, i64, u32, u64整数let x: i32 = 42;
f32, f64浮点数let pi: f64 = 3.14;
bool布尔值let t = true;
charUnicode 字符let c: char = 'A';

复合类型

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

// 数组(固定长度,相同类型)
let arr: [i32; 5] = [1, 2, 3, 4, 5];
let first = arr[0];
let zeros = [0; 10];  // [0, 0, ..., 0]

结构体

// 普通结构体
struct User {
    username: String,
    email: String,
    active: bool,
}

// 元组结构体
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

// 单元结构体(无字段)
struct AlwaysEqual;

// 方法实现
impl User {
    fn new(username: String, email: String) -> Self {
        User {
            username,
            email,
            active: true,
        }
    }
    
    fn is_active(&self) -> bool {
        self.active
    }
}

枚举与模式匹配

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

// 模式匹配
fn handle_message(msg: Message) {
    match msg {
        Message::Quit => println!("退出"),
        Message::Move { x, y } => println!("移动到 ({}, {})", x, y),
        Message::Write(text) => println!("消息:{}", text),
        Message::ChangeColor(r, g, b) => println!("颜色 ({}, {}, {})", r, g, b),
    }
}

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

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

// match 处理 Option
match some_number {
    Some(n) => println!("数字:{}", n),
    None => println!("无值"),
}

// if let 简化
if let Some(n) = some_number {
    println!("数字:{}", n);
}

第二部分 借用与引用

2.1 引用基础(⭐⭐⭐⭐⭐)

// 不可变引用
fn main() {
    let s = String::from("hello");
    let len = calculate_length(&s);  // &s 创建引用
    println!("{}", s);  // s 仍有效
}

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

// 可变引用
fn main() {
    let mut s = String::from("hello");
    change(&mut s);
    println!("{}", s);  // "hello, world"
}

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

2.2 借用规则(⭐⭐⭐⭐⭐)

规则 1: 在任意给定时刻,你只能拥有以下之一:
  - 一个可变引用
  - 任意数量的不可变引用

规则 2: 引用必须始终有效(无悬垂引用)

规则示例

// ✅ 多个不可变引用
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} {}", r1, r2);

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

// ✅ 作用域分离
let mut s = String::from("hello");
{
    let r1 = &s;
    let r2 = &s;
    println!("{} {}", r1, r2);
}  // r1, r2 作用域结束
let r3 = &mut s;  // 正确
r3.push_str("!");

// ✅ 可变引用使用后不能再借用
let mut s = String::from("hello");
let r1 = &mut s;
r1.push_str(",");
// let r2 = &mut s;  // 错误!r1 仍在使用

2.3 悬垂引用

// ❌ 错误:悬垂引用
// fn dangling_reference() -> &String {
//     let s = String::from("hello");
//     &s  // s 离开作用域后被释放
// }

// ✅ 正确:返回所有权
fn no_dangle() -> String {
    let s = String::from("hello");
    s
}

2.4 切片(Slice)

// 字符串切片
let s = String::from("hello world");
let hello = &s[0..5];   // "hello"
let world = &s[6..11];  // "world"
let hello = &s[..5];    // 省略开头
let world = &s[6..];    // 省略结尾
let all = &s[..];       // 整个字符串

// 函数参数使用切片
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[..]
}

// 数组切片
let arr = [1, 2, 3, 4, 5];
let slice = &arr[1..3];  // [2, 3]

第三部分 生命周期

3.1 生命周期基础(⭐⭐⭐⭐)

定义:生命周期是引用的有效作用域,确保引用在使用期间始终有效。

为什么需要生命周期

// ❌ 无法编译:编译器无法确定返回引用的生命周期
// fn longest(x: &str, y: &str) -> &str {
//     if x.len() > y.len() {
//         x
//     } else {
//         y
//     }
// }

// ✅ 正确:显式标注生命周期
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

3.2 生命周期注解语法

// 基本语法
fn func<'a>(x: &'a str, y: &'a str) -> &'a str { ... }

// 多个生命周期参数
fn multi_lifetime<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
    x  // 返回与 x 相同生命周期的引用
}

// 结构体中的生命周期
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!("注意:{}", announcement);
        self.part  // 生命周期省略
    }
}

3.3 生命周期省略规则

三条规则

规则 1: 每个引用参数获得独立的生命周期参数
规则 2: 如果只有一个输入生命周期,它被赋给所有输出生命周期
规则 3: 如果有 &self 或 &mut selfself 的生命周期被赋给所有输出生命周期

省略示例

// 应用规则 2
fn first_word(s: &str) -> &str {
    // 实际是:fn first_word<'a>(s: &'a str) -> &'a str
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}

// 应用规则 3
impl<'a> ImportantExcerpt<'a> {
    fn level(&self) -> i32 {
        // 实际是:fn level(&'a self) -> i32
        3
    }
    
    fn announce_and_return_part(&self, announcement: &str) -> &str {
        // self: &'a self, announcement: &'b str
        // 返回 &'a str(与 self 相同)
        self.part
    }
}

3.4 'static 生命周期

// 'static 表示引用在整个程序运行期间有效
let s: &'static str = "静态字符串";

// 字面量都是 'static
const GREETING: &'static str = "Hello!";

// 注意:'static 不表示值不能改变,只表示引用有效时间长

3.5 常见面试题

Q1: 以下代码能否编译?为什么?

fn main() {
    let s1 = String::from("long string");
    let s2 = String::from("short");
    let result = longest(s1.as_str(), s2.as_str());
    println!("{}", result);
}

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

答案: ✅ 可以编译。s1s2 的生命周期相同(整个 main 函数),返回的引用有效。

Q2: 什么时候必须手动标注生命周期?

答案:

  1. 函数返回引用且多个参数是引用
  2. 结构体包含引用字段
  3. impl 块中方法返回引用且与 self 无关

第四部分 智能指针

4.1 Box(⭐⭐⭐⭐)

用途:堆上分配数据的所有权指针

// 基本使用
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))))));

// 已知大小类型
struct Node {
    value: i32,
    next: Box<Option<Node>>,
}

4.2 Rc(⭐⭐⭐⭐)

用途:引用计数,多所有者(单线程)

use std::rc::Rc;

// 基本使用
let a = Rc::new(String::from("Hello"));
let b = Rc::clone(&a);  // 增加引用计数
let c = Rc::clone(&a);

println!("引用计数:{}", Rc::strong_count(&a));  // 3

// 树形结构
enum Tree {
    Node(i32, Vec<Rc<Tree>>),
    Leaf,
}

4.3 RefCell(⭐⭐⭐⭐)

用途:内部可变性,运行时借用检查

use std::cell::RefCell;

// 基本使用
let data = RefCell::new(5);
println!("data = {:?}", data.borrow());

*data.borrow_mut() = 10;  // 可变借用
println!("data = {:?}", data.borrow());

// 组合使用:Rc<RefCell<T>>
use std::rc::Rc;

let shared = Rc::new(RefCell::new(vec![1, 2, 3]));
let a = Rc::clone(&shared);
let b = Rc::clone(&shared);

a.borrow_mut().push(4);
println!("{:?}", b.borrow());  // [1, 2, 3, 4]

4.4 智能指针对比

类型所有权可变性检查时机线程安全
Box单一可变/不可变编译期
Rc多所有者不可变编译期
RefCell单一内部可变运行时
Arc多所有者不可变编译期
Mutex单一内部可变运行时

4.5 组合模式

// Rc<RefCell<T>> - 多所有者 + 可变
use std::rc::Rc;
use std::cell::RefCell;

let shared = Rc::new(RefCell::new(5));
let a = Rc::clone(&shared);
let b = Rc::clone(&shared);

*shared.borrow_mut() = 10;
println!("a={}, b={}, shared={}", a.borrow(), b.borrow(), shared.borrow());

// Arc<Mutex<T>> - 多线程 + 可变
use std::sync::{Arc, Mutex};

let data = Arc::new(Mutex::new(5));
let mut handles = vec![];

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

for handle in handles {
    handle.join().unwrap();
}
println!("Result: {}", *data.lock().unwrap());

第五部分 trait 与泛型

5.1 泛型基础(⭐⭐⭐)

// 泛型函数
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 Pair<T, U> {
    first: T,
    second: U,
}

5.2 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 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 struct Tweet {
    pub username: String,
    pub content: String,
}

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

5.3 trait bound

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

// 多 trait bound
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,
{
    42
}

// impl Trait 语法
fn returns_summarizable() -> impl Summary {
    Tweet {
        username: String::from("horse_ebooks"),
        content: String::from("of course"),
    }
}

5.4 常用标准库 trait

// Display vs Debug
use std::fmt;

struct Point {
    x: i32,
    y: i32,
}

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

impl fmt::Debug for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Point")
            .field("x", &self.x)
            .field("y", &self.y)
            .finish()
    }
}

// Clone vs Copy
#[derive(Clone)]
struct MyData {
    data: Vec<u8>,
}

#[derive(Copy, Clone)]
struct MyPoint {
    x: i32,
    y: i32,
}

// PartialEq vs Eq
#[derive(PartialEq)]
struct Partial {
    value: f32,
}

#[derive(Eq, PartialEq)]
struct Equal {
    value: i32,
}

// PartialOrd vs Ord
#[derive(PartialOrd, Ord, PartialEq, Eq)]
struct MyOrder {
    priority: u32,
}

5.5 关联类型与泛型 trait

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

// 实现
struct Counter {
    count: u32,
}

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

// 泛型 trait
trait Container<T> {
    fn contains(&self, item: &T) -> bool;
}

第六部分 错误处理

6.1 panic! 与 Result(⭐⭐⭐⭐)

// panic! - 不可恢复错误
fn main() {
    panic!("crash and burn!");
}

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

// 使用 Result
use std::fs::File;

let f = File::open("hello.txt");

let f = match f {
    Ok(file) => file,
    Err(error) => panic!("打开文件失败:{:?}", error),
};

// 传播错误
use std::io::{self, Read};
use std::fs::File;

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

// ? 操作符简化
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)
}

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

6.2 错误传播模式

// main 返回 Result
use std::error::Error;
use std::fs::File;

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

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

#[derive(Debug)]
enum MyError {
    Io(std::io::Error),
    Parse(std::num::ParseIntError),
}

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            MyError::Io(e) => write!(f, "IO 错误:{}", e),
            MyError::Parse(e) => write!(f, "解析错误:{}", e),
        }
    }
}

impl Error for MyError {}

impl From<std::io::Error> for MyError {
    fn from(err: std::io::Error) -> MyError {
        MyError::Io(err)
    }
}

impl From<std::num::ParseIntError> for MyError {
    fn from(err: std::num::ParseIntError) -> MyError {
        MyError::Parse(err)
    }
}

6.3 thiserror 与 anyhow

// thiserror - 库推荐
use thiserror::Error;

#[derive(Error, Debug)]
enum DataError {
    #[error("数据未找到:{0}")]
    NotFound(String),
    #[error("网络请求失败")]
    Request(#[from] reqwest::Error),
    #[error("IO 错误")]
    Io(#[from] std::io::Error),
}

// anyhow - 应用推荐
use anyhow::{Result, Context, bail};

fn read_config(path: &str) -> Result<String> {
    let content = std::fs::read_to_string(path)
        .with_context(|| format!("无法读取配置文件:{}", path))?;
    
    if content.is_empty() {
        bail!("配置文件为空");
    }
    
    Ok(content)
}

第七部分 异步编程与 Tokio

7.1 Future 基础(⭐⭐⭐⭐⭐)

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

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

// async/await 语法
async fn fetch_data() -> String {
    // 异步操作
    "data".to_string()
}

// async fn 返回的是 Future
fn returns_future() -> impl Future<Output = String> {
    async { "data".to_string() }
}

7.2 Tokio 运行时(⭐⭐⭐⭐⭐)

use tokio;

// 多线程运行时(默认)
#[tokio::main]
async fn main() {
    println!("Hello from Tokio!");
}

// 单线程运行时
#[tokio::main(flavor = "current_thread")]
async fn main() {
    // 适合纯 I/O 密集型
}

// 手动创建运行时
use tokio::runtime::Runtime;

fn main() {
    let rt = Runtime::new().unwrap();
    rt.block_on(async {
        println!("Hello!");
    });
}

7.3 任务管理

// spawn 创建任务
#[tokio::main]
async fn main() {
    let handle = tokio::spawn(async {
        println!("任务执行中");
        42
    });
    
    let result = handle.await.unwrap();
    println!("任务结果:{}", result);
}

// 并发执行多个任务
#[tokio::main]
async fn main() {
    let task1 = tokio::spawn(async {
        tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
        "task1"
    });
    
    let task2 = tokio::spawn(async {
        tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
        "task2"
    });
    
    let (r1, r2) = tokio::join!(task1, task2);
    println!("{}, {}", r1.unwrap(), r2.unwrap());
}

// select 等待第一个完成
#[tokio::main]
async fn main() {
    tokio::select! {
        result = task1() => println!("task1 完成:{}", result),
        result = task2() => println!("task2 完成:{}", result),
    }
}

7.4 异步 I/O

use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let listener = TcpListener::bind("127.0.0.1:8080").await?;
    
    loop {
        let (mut socket, addr) = listener.accept().await?;
        
        tokio::spawn(async move {
            let mut buf = [0; 1024];
            let n = socket.read(&mut buf).await.unwrap();
            socket.write_all(&buf[..n]).await.unwrap();
        });
    }
}

7.5 同步原语

use tokio::sync::{Mutex, RwLock, mpsc, oneshot, Semaphore};

// Mutex
let m = Mutex::new(5);
{
    let mut num = m.lock().await;
    *num = 6;
}

// RwLock
let rw = RwLock::new(5);
{
    let read = rw.read().await;  // 多个读
}
{
    let write = rw.write().await;  // 独占写
    *write = 10;
}

// mpsc channel(多生产者单消费者)
let (tx, mut rx) = mpsc::channel(32);
tokio::spawn(async move {
    tx.send("hello").await.unwrap();
});
let msg = rx.recv().await.unwrap();

// oneshot channel(单次通信)
let (tx, rx) = oneshot::channel();
tokio::spawn(async move {
    tx.send(42).unwrap();
});
let result = rx.await.unwrap();

// Semaphore(限流)
let sem = Semaphore::new(3);
let permit = sem.acquire().await.unwrap();
// 临界区
drop(permit);  // 释放许可

7.6 超时与间隔

use tokio::time::{timeout, interval, sleep, Duration};

// 超时
match timeout(Duration::from_secs(5), async_op()).await {
    Ok(result) => println!("完成:{}", result),
    Err(_) => println!("超时"),
}

// 定时器
sleep(Duration::from_secs(1)).await;

// 间隔定时器
let mut int = interval(Duration::from_secs(1));
for _ in 0..5 {
    int.tick().await;
    println!("tick");
}

第八部分 并发编程

8.1 线程基础(⭐⭐⭐⭐)

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

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

// 等待线程完成
handle.join().unwrap();

// 线程传值
let v = vec![1, 2, 3];
let handle = thread::spawn(move || {  // move 转移所有权
    println!("{:?}", v);
});
handle.join().unwrap();

8.2 消息传递

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

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

thread::spawn(move || {
    tx.send("hello").unwrap();
});

let msg = rx.recv().unwrap();  // 阻塞接收
println!("收到:{}", msg);

// 多生产者
let (tx, rx) = mpsc::channel();
let tx1 = tx.clone();

thread::spawn(move || {
    tx1.send("from tx1").unwrap();
});

thread::spawn(move || {
    tx.send("from tx2").unwrap();
});

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

8.3 共享状态

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

// Mutex
let m = Mutex::new(5);
{
    let mut num = m.lock().unwrap();
    *num = 6;
}

// Arc + Mutex(多线程共享)
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!("结果:{}", *counter.lock().unwrap());

8.4 Send 与 Sync trait

// Send: 可在线程间转移所有权
// Sync: 可在线程间共享引用(&T 是 Send)

// 自动实现:所有基本类型
// 不实现:Rc<T>(引用计数非原子)

fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}

fn main() {
    assert_send::<i32>();   // ✅
    assert_sync::<i32>();   // ✅
    
    assert_send::<Rc<i32>>();  // ❌
    assert_sync::<Rc<i32>>();  // ❌
    
    assert_send::<Arc<i32>>();  // ✅
    assert_sync::<Arc<i32>>();  // ✅
}

8.5 原子类型

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;

let counter = Arc::new(AtomicUsize::new(0));
let mut handles = vec![];

for _ in 0..10 {
    let counter = Arc::clone(&counter);
    let handle = thread::spawn(move || {
        counter.fetch_add(1, Ordering::SeqCst);
    });
    handles.push(handle);
}

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

println!("结果:{}", counter.load(Ordering::SeqCst));

第九部分 内存管理与 unsafe

9.1 内存布局

栈(Stack)          堆(Heap)
┌─────────────┐     ┌─────────────┐
│ 局部变量     │     │ Box 数据     │
│ 函数参数     │     │ String 数据  │
│ 返回地址     │     │ Vec 数据     │
└─────────────┘     └─────────────┘

9.2 unsafe Rust

// unsafe 允许的操作:
// 1. 解引用裸指针
// 2. 调用 unsafe 函数
// 3. 访问可变静态变量
// 4. 实现 unsafe trait

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

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

// unsafe 函数
unsafe fn dangerous() {
    // 不安全操作
}

unsafe {
    dangerous();
}

// 调用外部代码
extern "C" {
    fn abs(input: i32) -> i32;
}

unsafe {
    println!("绝对值:{}", abs(-3));
}

9.3 内存泄漏

// 可能的泄漏
use std::cell::RefCell;
use std::rc::Rc;

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

// 循环引用导致泄漏
let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));
let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));

// 修复:使用 Weak
use std::rc::Weak;

let a = Rc::new(Cons(5, RefCell::new(Weak::new())));

9.4 Pin 与 Unpin

use std::pin::Pin;
use std::marker::Unpin;

// Pin 用于自引用结构
use std::pin::Pin;

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

// !Unpin 类型需要 Pin
let mut data = String::from("hello");
let pin = Pin::new(&mut data);

// async/await 生成的 Future 通常是 !Unpin
async fn foo() {}
let future = foo();
tokio::pin!(future);  // 固定 Future

第十部分 高频面试题速查

10.1 Rust 基础

问题关键词
Rust 为什么不需要 GC?所有权系统、RAII
move 语义是什么?所有权转移、深拷贝 vs 浅拷贝
Copy trait 作用?栈上拷贝、自动复制
drop 如何工作?Drop trait、作用域结束
match 与 if let 区别?穷尽检查、简化语法

10.2 所有权与借用

问题关键词
所有权三大规则单一所有者、作用域释放
借用规则可变/不可变互斥
什么是悬垂引用?引用无效、编译错误
切片的作用?引用连续内存、&str
&str vs String切片 vs 所有权、栈 vs 堆

10.3 生命周期

问题关键词
生命周期作用防止悬垂引用
生命周期省略规则三条规则
'static 含义程序整个运行期
何时需要标注生命周期?返回引用、多参数

10.4 智能指针

问题关键词
Box vs Rc vs Arc单所有者、多所有者、线程安全
RefCell 作用内部可变性、运行时检查
Rc<RefCell> 场景多所有者 + 可变
Arc<Mutex> 场景多线程 + 可变
内存泄漏如何产生?循环引用

10.5 trait 与泛型

问题关键词
trait 与接口区别默认实现、关联类型
trait bound 语法T: Trait、where
impl Trait 用法返回类型、匿名类型
dyn trait 是什么?动态分发、trait 对象
Send vs Sync线程转移、线程共享

10.6 错误处理

问题关键词
panic! vs Result不可恢复、可恢复
? 操作符原理错误传播、From trait
thiserror vs anyhow库、应用
自定义错误类型Error trait、From 实现

10.7 异步编程

问题关键词
Future 工作原理poll、状态机
async/await 原理状态机、挂起点
Tokio 运行时架构调度器、Reactor
spawn vs block_on任务创建、阻塞等待
select! 宏作用多 Future 竞争

10.8 并发编程

问题关键词
线程创建方式thread::spawn、move
消息传递 vs 共享状态channel、Mutex
Mutex vs Atomic锁、原子操作
mpsc vs oneshot多生产者、单次
数据竞争如何防止?所有权、借用检查

附录 A. 复习优先级

第一梯队(必会):
✅ 所有权与借用规则
✅ 生命周期基础
✅ 智能指针(Box/Rc/Arc/Mutex)
✅ trait 与泛型
✅ 错误处理(Result/?)
✅ Tokio 异步基础

第二梯队(高频):
✅ 模式匹配
✅ 切片与字符串
✅ 并发编程
✅ unsafe 基础

第三梯队(加分):
✅ Pin/Unpin
✅ 自定义错误类型
✅ Tokio 高级特性
✅ 性能优化

附录 B. 推荐资源