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 的能力:
- 解
引用原始指针
- 调
用不安全函数或方法
- 访
问或修改可变静态变量
- 实
现不安全 trait
- 访
问 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_case | user_name |
| 函数 | snake_case | get_user |
| 结构体 | PascalCase | UserName |
| 枚举 | PascalCase | Color |
| trait | PascalCase | Printable |
| 常量 | SCREAMING_SNAKE_CASE | MAX_SIZE |
| 模块 | snake_case | user_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. 学习资源汇总
免费在线资源
- <
strong>Rust 圣经(The Rust Programming Language)
- 英文版:https://doc.rust-lang.org/stable/book/
- 中文版:https://kaisery.github.io/trpl-zh-cn/
- 最佳入门教程,系统全面
- <
strong>Rust by Example
- 中文版:https://rustwiki.org/zh-CN/rust-by-example/
- 通过示例学习
- <
strong>Rustlings
- https://github.com/rust-lang/rustlings
- 交互式练习,修复编译错误
- <
strong>Rust 在线编辑器
- https://play.rust-lang.org/
- 在线编写和运行 Rust 代码
- <
strong>Rust 标准库文档
- https://doc.rust-lang.org/std/
- 完整的 API 文档
推荐书籍
- 《Rust 程序设计语言》(官方中文版)
- 《Rust 权威指南》
- 《深入浅出 Rust》
- 《Rust 编程:入门、实战与进阶》
社区
- Rust 中文社区:https://rustcc.cn/
- Rust 官方论坛:https://users.rust-lang.org/
- GitHub:https://github.com/rust-lang
祝学习愉快!Rust 是一门值得投入学习的语言。 🦀