← 返回首页← 专题总览

Rust 高级特性与并发编程

// Rust 自动为大多数类型实现 Send 和 Sync
前端架构师通关手册 · 专题 20

--- 接续 ---

Mutex

use std::sync::Mutex;

fn main() {
    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;

fn main() {
    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());
}

Send 和 Sync

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

// Rust 自动为大多数类型实现 Send 和 Sync
// 原始指针 *const T 和 *mut T 没有实现 Send 和 Sync

Demo 13.1:多线程下载器(模拟)

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

fn main() {
    let urls = vec![
        "https://example.com/file1.txt",
        "https://example.com/file2.txt",
        "https://example.com/file3.txt",
        "https://example.com/file4.txt",
    ];
    
    let results = Arc::new(Mutex::new(Vec::new()));
    let mut handles = vec![];
    
    for url in urls {
        let results = Arc::clone(&results);
        let handle = thread::spawn(move || {
            // 模拟下载
            println!("开始下载: {}", url);
            thread::sleep(Duration::from_millis(100));
            let content = format!("{} 的内容", url);
            results.lock().unwrap().push(content);
            println!("完成下载: {}", url);
        });
        handles.push(handle);
    }
    
    for handle in handles {
        handle.join().unwrap();
    }
    
    let results = results.lock().unwrap();
    println!("下载完成,共 {} 个文件:", results.len());
    for content in results.iter() {
        println!("  - {}", content);
    }
}

第十四部分:高级特性

14.1 不安全 Rust

对应官方文档 Chapter 20.1: Unsafe Rust
fn main() {
    let mut num = 5;
    
    // 原始指针
    let r1 = &num as *const i32;
    let r2 = &mut num as *mut i32;
    
    // 解引用原始指针需要 unsafe
    unsafe {
        println!("r1 是: {}", *r1);
        println!("r2 是: {}", *r2);
    }
    
    // 调用不安全函数
    unsafe {
        dangerous();
    }
    
    // 安全抽象
    let mut v = vec![1, 2, 3, 4, 5, 6];
    let r = &mut v[..];
    let (a, b) = split_at_mut(r, 3);
    
    assert_eq!(a, &mut [1, 2, 3]);
    assert_eq!(b, &mut [4, 5, 6]);
}

unsafe fn dangerous() {}

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 {
        (
            std::slice::from_raw_parts_mut(ptr, mid),
            std::slice::from_raw_parts_mut(ptr.add(mid), len - mid),
        )
    }
}
不安全 Rust 的能力:
  1. 解
引用原始指针
  1. 调
用不安全函数或方法
  1. 访
问或修改可变静态变量
  1. 实
现不安全 trait
  1. 访
问 union 的字段 使用 unsafe 的常见场景:

extern 函数

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

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

// 导出 Rust 函数给 C 使用
#[no_mangle]
pub extern "C" fn call_from_c() {
    println!("来自 C 的调用");
}

14.2 高级 Trait

关联类型

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

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> {
        self.count += 1;
        if self.count < 6 {
            Some(self.count)
        } else {
            None
        }
    }
}

默认泛型参数

use std::ops::Add;

#[derive(Debug, PartialEq)]
struct Millimeters(u32);
struct Meters(u32);

impl Add<Meters> for Millimeters {
    type Output = Millimeters;
    
    fn add(self, other: Meters) -> Millimeters {
        Millimeters(self.0 + (other.0 * 1000))
    }
}

完全限定语法

trait Pilot {
    fn fly(&self);
}

trait Wizard {
    fn fly(&self);
}

struct Human;

impl Pilot for Human {
    fn fly(&self) {
        println!("机长说你好");
    }
}

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

impl Human {
    fn fly(&self) {
        println!("挥手");
    }
}

fn main() {
    let person = Human;
    person.fly();           // 默认调用 Human 的方法
    Pilot::fly(&person);    // 调用 Pilot trait
    Wizard::fly(&person);   // 调用 Wizard trait
}

// 完全限定语法
// <Type as Trait>::function(receiver_if_method, next_arg, ...);

Supertrait

use std::fmt;

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

newtype 模式

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

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

14.3 高级类型

类型别名

type Kilometers = i32;

fn main() {
    let x: i32 = 5;
    let y: Kilometers = 5;
    println!("x + y = {}", x + y);
}

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

fn takes_long_type(f: Thunk) {
    // ...
}

fn returns_long_type() -> Thunk {
    Box::new(|| println!("hi"))
}

Never 类型

// ! 类型(never type)表示永不返回
fn bar() -> ! {
    panic!()
}

// 用途:continue、panic!、loop + break

14.4 高级函数与闭包

函数指针

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

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

fn main() {
    let answer = do_twice(add_one, 5);
    println!("答案是: {}", answer);  // 12
    
    // fn 是一个类型,实现了所有 Fn trait
    let list_of_numbers = vec![1, 2, 3];
    let list_of_strings: Vec<String> = list_of_numbers
        .iter()
        .map(|i| i.to_string())
        .collect();
    
    // 也可以使用函数指针
    let list_of_strings: Vec<String> = list_of_numbers
        .iter()
        .map(ToString::to_string)
        .collect();
}

返回闭包

// ❌ 错误:闭包大小未知
// fn returns_closure() -> dyn Fn(i32) -> i32 {
//     |x| x + 1
// }

// ✅ 正确:使用 Box 包装
fn returns_closure() -> Box<dyn Fn(i32) -> i32> {
    Box::new(|x| x + 1)
}

14.5 宏

对应官方文档 Chapter 20.5: Macros

声明宏(macro_rules!)

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

fn main() {
    let v = vec![1, 2, 3];
    println!("{:?}", v);
}

过程宏

// 过程宏的定义在单独的 crate 中
// 有三种类型:
// 1. 类属性过程宏(derive)
// 2. 类函数过程宏
// 3. 类属性宏

// 使用 derive 的例子
#[derive(Debug, Clone, PartialEq)]
struct Point {
    x: i32,
    y: i32,
}

// derive 自动生成 trait 实现

编写自定义 derive 宏

// hello_macro.rs
pub trait HelloMacro {
    fn hello_macro();
}

// hello_macro_derive.rs(单独的 proc-macro crate)
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::DeriveImpl) -> 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()
}

第十五部分:常用模式

对应官方文档 Chapter 19: Patterns and Matching

15.1 模式匹配语法

fn main() {
    // 字面量
    let x = 1;
    match x {
        1 => println!("one"),
        2 => println!("two"),
        _ => println!("other"),
    }
    
    // 命名变量
    let x = Some(5);
    let y = 10;
    match x {
        Some(50) => println!("Got 50"),
        Some(y) => println!("Matched, y = {:?}", y),
        _ => println!("Default case, x = {:?}", x),
    }
    
    // 多模式
    let x = 1;
    match x {
        1 | 2 => println!("one or two"),
        _ => println!("other"),
    }
    
    // 范围
    let x = 5;
    match x {
        1..=5 => println!("one through five"),
        _ => println!("other"),
    }
    
    // 解构结构体
    struct Point { x: i32, y: i32 }
    let p = Point { x: 0, y: 7 };
    let Point { x: a, y: b } = p;
    
    // 简写
    let Point { x, y } = p;
    
    // 解构枚举
    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),
        Message::Write(text) => println!("Write: {}", text),
        Message::ChangeColor(r, g, b) => println!("Color ({}, {}, {})", r, g, b),
    }
    
    // 嵌套解构
    let num = 4u8;
    match num {
        1 => println!("One"),
        2 | 3 | 5 | 7 | 11 => println!("This is a prime"),
        13..=19 => println!("A teen"),
        _ => println!("Ain't special"),
    }
    
    // 忽略值
    let mut setting_value = Some(5);
    let new_setting_value = Some(10);
    match (setting_value, new_setting_value) {
        (Some(_), Some(_)) => println!("Can't overwrite"),
        _ => setting_value = new_setting_value,
    }
    
    // .. 忽略剩余部分
    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 % 2 == 0 => println!("Even"),
        Some(x) => println!("Odd"),
        None => (),
    }
    
    // @ 绑定
    enum Greeting { Hello { id: i32 } }
    let msg = Greeting::Hello { id: 5 };
    match msg {
        Greeting::Hello { id: id_variable @ 3..=7 } => println!("Found an id in range: {}", id_variable),
        Greeting::Hello { id: 10..=12 } => println!("Found an id in another range"),
        Greeting::Hello { id } => println!("Found some other id: {}", id),
    }
}

let-else(Rust 1.65+)

fn main() {
    let Some(x) = Some(5) else {
        return;
    };
    println!("x = {}", x);
}

15.2 let 语句中的模式

fn main() {
    // 元组解构
    let (x, y, z) = (1, 2, 3);
    
    // 函数参数中的模式
    let point = (3, 5);
    print_coordinates(&point);
}

fn print_coordinates(&(x, y): &(i32, i32)) {
    println!("当前坐标: ({}, {})", x, y);
}

附录

A. Rust 编码规范

命名规范

类型规范示例
变量snake_caseuser_name
函数snake_caseget_user
结构体PascalCaseUserName
枚举PascalCaseColor
traitPascalCasePrintable
常量SCREAMING_SNAKE_CASEMAX_SIZE
模块snake_caseuser_module
宏snake_case!println!

格式化

# 格式化代码
cargo fmt

# 检查但不修改
cargo fmt --check

# 运行 clippy 检查
cargo clippy

B. 常用 Cargo 命令

# 新建项目
cargo new project_name
cargo new --lib lib_name

# 构建
cargo build            # debug 模式
cargo build --release  # release 模式(优化)

# 运行
cargo run

# 检查编译错误(不生成可执行文件,更快)
cargo check

# 运行测试
cargo test

# 生成文档
cargo doc --open

# 添加依赖
cargo add package_name

# 更新依赖
cargo update

# 清理构建
cargo clean

# 构建特定目标
cargo build --target x86_64-pc-windows-msvc

C. 错误信息解读

错误类型含义解决方案
cannot borrow as mutable试图可变借用不可变变量添加 mut
value used after move使用已移动的值使用 clone() 或引用
lifetime mismatch生命周期不匹配添加生命周期标注
trait not implemented缺少 trait 实现实现相应 trait 或使用 derive
unused variable未使用的变量使用 _ 前缀或删除
expected type, found类型不匹配检查类型标注
cannot infer type无法推断类型添加类型标注

D. 学习资源汇总

免费在线资源

  1. <
strong>Rust 圣经(The Rust Programming Language)
  1. <
strong>Rust by Example
  1. <
strong>Rustlings
  1. <
strong>Rust 在线编辑器
  1. <
strong>Rust 标准库文档

推荐书籍

社区


祝学习愉快!Rust 是一门值得投入学习的语言。 🦀