1. Rust与C/C++的区别
Rust可以替换C/C++,和他们有同样的性能,但是很多bug在编译时就被消灭了。
它更善于以下场景
- 需要运行速度
- 需要内存安全
- 需要更好的利用多处理器
1. 内存管理:手动 vs 所有权系统
Rust是一个用栈内存管理堆内存的设计,所以作用域(函数)结束,运行栈的数据会被全部释放,如果后面还有要用的数据,要么返回(移交所有权),要么提前说明是借用(可变引用或不可变引用)(借别人的就得还);这就是内存管理的精髓

C/C++ 怎么做
- C:
malloc/free,很容易: - 忘记
free→ 内存泄漏 - 重复
free→ 野指针、崩溃
- C++:
new/delete+ RAII/智能指针(std::unique_ptr等) - 写得好很安全,但要自觉、要有规范
Rust 怎么做
Rust 禁止手动 free,通过「所有权」和「作用域」在编译期自动管理:
关键规则只有三条:
- 每个值有且只有一个所有者(owner)
- 所有者离开作用域时,值会被自动释放
- 同一时刻(只能有一个主人):
- 要么有任意多个不可变引用
&T(也就是读随便你读) - 要么有一个可变引用
&mut T,不能混用 (写时同一时刻只能有一个写)
感受差异:
- C/C++:内存安全靠程序员经验和自觉
- Rust:编译器强制你写出「不会有悬垂指针、UAF(use-after-free)」的代码,否则不让编译过,这点非常关键:设备跑久了不崩,不泄漏。
2. 空指针 & 错误处理:裸指针 vs Option / Result
C/C++:NULL / nullptr + 错误码或异常
很多 BUG 都是「忘了判空」,或者「return -1 表示错误,但上层没处理」。
Rust:没有「空指针」这个类型,用枚举强制你处理
- 没有「默认可以是空」的指针
- 用:
示例:
差异点:
- C:
NULL+ 注释告诉你「可能为空」
- Rust:类型系统直接告诉你「这个函数可能没有值/会失败」,不处理就过不了编译,Rust 会强迫你都考虑到。
3. 并发与多线程:野蛮 vs 编译期保护
C/C++:线程安全全靠规范
- 多线程时:
- 不加锁 → 数据竞争
- 加锁忘了释放 → 死锁
- 用错锁 → 逻辑乱
Rust:设计目标就是「无数据竞争的并发」
核心思想:
- 只要有数据竞争风险的代码,一律编译不过
Send/Sync这两个 trait,控制「什么类型能在线程间移动 / 共享」
示例:
要在多线程之间共享数据,你必须显式使用:
Arc<T>:原子引用计数,线程安全的共享指针
Mutex<T>:互斥锁
- 或者
channel:消息传递
差异:
- C/C++:你想干啥都行,但错了就 UB(未定义行为)
- Rust:你只有「安全地干」这一条路(当然也可以
unsafe强行绕过,但需要你非常清楚自己在干啥)
4. 语言特性:更现代、约束更多
4.1 所有权 + 借用 vs 借引用自己约束
在 C++ 里你经常会写:
Rust 里借用概念被提升到核心语言层级:
区别在于:
- Rust 有 borrow checker(借用检查器),在编译时验证:
- 不会有悬垂引用
- 同一时间只有一个
&mut或多个&
- C++ 靠你自觉,语法本身不会帮你做严格检查
4.2 泛型 & trait vs 模板 & 继承
- C++:模板(template)+ 虚函数 / 继承
- Rust:泛型 + trait(更偏向接口 + 约束)
对这种以后会有「LED、继电器、传感器」等不同设备类型的场景,trait 非常适合抽象接口,比 C++ 继承+虚函数更「松耦合」。
1.5 工具链与生态:cargo 一站式 vs 各种 build 系统
C/C++ 常见情况
- 构建系统:
Makefile/ CMake / qmake / autotools 等
- 依赖管理:
- 自己下载源码,放到项目里
- 或者系统包管理器(
apt,yum等)
不同项目结构都不一样,需要你自己整。
Rust:全都交给 cargo
一个命令初始化项目:
依赖管理、构建、测试、格式化,一条龙:
依赖写在
Cargo.toml 里:你在 Linux 上写 Matter Controller / 服务端逻辑时:
- 想用 HTTP 客户端、MQTT、数据库,只要在
Cargo.toml添一行,然后cargo build就能自动拉下来
- 不用自己折腾库路径、版本冲突(一部分工作交给了 Cargo)
1.6 运行时 & 性能:接近 C,但更可控
共同点
- 都是编译型语言,生成机器码
- 性能上基本同级(Rust 通常和 C++ 打个平手,甚至有场景更快)
不同点
- Rust 没有 GC(垃圾回收),性能可预测,适合嵌入式
- Rust 引用在语义上更接近「受约束的指针」
panic(类似断言失败)默认不会像 C++ 异常那样无处不在,它是显式的,且可以在嵌入式环境下关闭 unwind 改为 abort
对于 ESP32 / Linux 这种场景:
- ESP32:可以用
no_std+ 特定运行时,控制栈、堆的使用,甚至替换分配器
- Linux:可以直接用完整标准库,配合
tokio之类的异步运行时写高并发服务
1.7 unsafe:可以接近 C,但要「圈起来」
Rust 有
unsafe (不安全的)关键字,允许你:- 直接操作裸指针
- 调用 C 函数(FFI)
- 读写某些特殊内存(寄存器、MMIO 等)
关键区别:
- C:所有地方都「默认 unsafe」
- Rust:默认安全,只有
unsafe块里你要自己保证安全性,而且很醒目
在嵌入式(ESP32)开发里,这就很有用:
- 大部分逻辑用安全 Rust 写
- 必须直接操作寄存器或调用 ESP-IDF C API 的地方,用
unsafe包一小块
- 将风险范围缩到最小
8. 学 Rust 主要要「转的几个弯」
- 忘掉手动 free:
- 不要想着「我什么时候 free」
- 要想着「这个值应该归谁管?它的生命周期到哪?」
- 尤其是函数参数/返回值,先大胆用「按值传递」,编译器会帮你优化。
- 习惯
Option/Result: - 思维从「这个函数返回 NULL / -1」
- 转成「这个函数可能返回 None / Err,要么我处理,要么向上抛」。
- 接受借用检查器的“刁难”:
- 一开始会觉得编译器很烦,但每一个错误都是在防止潜在 bug
- 常见模式:先写成「克隆一份」(
clone()),跑通功能,再优化所有权设计。
- 习惯用
cargo管理项目: - 不再手写 Makefile / CMake
- 用
cargo new/cargo build/cargo run就够你 90% 的需求。
- 并发用通道/锁,不直接共享裸指针:
- 多线程优先考虑「消息传递」而不是「共享内存」
- 共享必须用
Arc<Mutex<T>>之类的包装。
2. Cargo
- 可以使用
cargo new创建项目。
- 可以使用
cargo init来初始化当前文件夹为项目文件夹
- 可以使用
cargo build构建项目。
- 可以使用
cargo build --release优化编译最终发布的版本
- 可以使用
cargo run一步构建并运行项目。
- 可以使用
cargo check在不生成二进制文件的情况下构建项目来检查错误。
- 可以使用
cargo add添加外部的依赖
- 可以使用
cargo update更新外部的依赖1
- 可以在 Crates.io 搜索依赖包,也可以直接
cargo search
你不可能凭空就知道应该 use 哪个 trait 以及该从 crate 中调用哪个方法,因此每个 crate 有使用说明文档。Cargo 的另一个很棒的功能是运行cargo doc --open命令来构建所有本地依赖提供的文档并在浏览器中打开。例如,假设你对randcrate 中的其他功能感兴趣,你可以运行cargo doc --open并点击左侧导航栏中的rand。
3. 初识(找数字游戏)
一个简单的模块, 介绍:
4. 基础语法
4.1 Rust 变量和常量详解
- 变量绑定:Rust 的变量默认为不可变(immutable),使用
let关键字绑定值。如果想要使变量可变,需要添加mut关键字。
- 可变性(mutability):通过在变量声明前添加
mut关键字,使变量可变,这样你可以在后续的代码中改变它的值。
- 常量:类似于不可变变量,常量 (constants) 是绑定到一个名称的不允许改变的值,常量在整个程序生命周期中都有效
- 变量和常量的区别:
- 常量使用const关键字,变量使用let关键字
- 常量必须标注类型,变量可以自动推断类型
- 常量的值必须是编译时已知的
- 常量可以在任何作用域中声明,包括全局作用域
- 常量只能被设置为常量表达式,无法绑定到函数的调用结果或只能在运行时才能计算出的值。
命名规范:Rust里,常量使用全大写字母,单词中间使用下划线分开例如:
const MAX_NUM:u32 = 100_000; 数字之间可以使用_ 来增强可读性4.2 Rust 数据类型详解
let tuple_1 = (10, "hello", 3.14); // 类型自动推断为(i32, &str, f64)
let tuple_2: (i32, &str, f64) = (20, "world", 2.71); // 显式指定类型
println!("n元组类型示例:");
println!("tuple_1: {:?}", tuple_1);
println!("tuple_2: {:?}", tuple_2);
// 解构元组
// 可以使用模式匹配来解构元组的值
let (x, y, z) = tuple_1;
println!("解构元组: x={}, y={}, z={}", x, y, z);
// 数组类型
// 数组是将多个相同类型的值组合在一起的方式
// 数组的长度是固定的,一旦声明就不能改变大小
let array_1 = [1, 2, 3, 4, 5]; // 类型自动推断为[i32; 5]
let array_2: [i32; 5] = [10, 20, 30, 40, 50]; // 显式指定类型和长度
let array_3 = [3; 5]; // 重复初始化:创建包含5个3的数组
println!("n数组类型示例:");
println!("array_1: {:?}", array_1);
println!("array_2: {:?}", array_2);
println!("array_3: {:?}", array_3);
// 访问数组元素
// 可以使用索引来访问数组中的元素,索引从0开始
println!("array_1[0]: {}, array_2[2]: {}", array_1[0], array_2[2]);
// 切片类型
// 切片允许我们引用集合中一段连续的元素序列,而不是整个集合
// 切片是引用,所以没有所有权
let slice_1 = &array_1[1..4]; // 引用array_1中从索引1到3的元素(不包含4)
let slice_2 = &array_2[..3]; // 引用array_2中从开始到索引2的元素
println!("n切片类型示例:");
println!("slice_1: {:?}", slice_1);
println!("slice_2: {:?}", slice_2);
}
// 函数定义
fn add(a: i32, b: i32) -> i32 {
a + b // 表达式作为返回值,不需要分号
}
// 带多个参数的函数
fn multiply(a: i32, b: i32, c: i32) -> i32 {
a b c
}
// 无返回值的函数
fn print_greeting(name: &str) {
println!("Hello, {}!", name);
}
// 带返回值的函数,使用return关键字
fn divide(a: i32, b: i32) -> i32 {
if b == 0 {
return 0; // 提前返回
}
a / b
}
// 函数参数可以有默认值
fn greet(name: &str, greeting: &str) {
println!("{} {}", greeting, name);
}
// 可变参数函数
fn sum(numbers: &[i32]) -> i32 {
let mut total = 0;
for &num in numbers {
total += num;
}
total
}
// 嵌套函数
fn outer_function() {
println!("This is the outer function");
fn inner_function() {
println!("This is the inner function");
}
inner_function();
}
// 函数作为参数
fn apply_function<F>(f: F, x: i32) -> i32
where F: Fn(i32) -> i32 {
f(x)
}
// 闭包作为函数参数
fn use_closure() {
let add_five = |x: i32| x + 5;
let result = apply_function(add_five, 10);
println!("闭包应用结果: {}", result);
}
fn main() {
// 调用简单函数
let result1 = add(5, 3);
println!("5 + 3 = {}", result1);
// 调用多参数函数
let result2 = multiply(2, 3, 4);
println!("2 3 4 = {}", result2);
// 调用无返回值函数
print_greeting("Rust Programmer");
// 调用带条件返回的函数
let result3 = divide(10, 2);
let result4 = divide(10, 0);
println!("10 / 2 = {}, 10 / 0 = {}", result3, result4);
// 调用带默认参数的函数
greet("Alice", "Hello");
greet("Bob", "Hi");
// 调用可变参数函数
let numbers = [1, 2, 3, 4, 5];
let total = sum(&numbers);
println!("数组求和: {}", total);
// 调用嵌套函数
outer_function();
// 调用闭包相关函数
use_closure();
// 函数指针
let add_ptr: fn(i32, i32) -> i32 = add;
let result5 = add_ptr(10, 20);
println!("通过函数指针调用: 10 + 20 = {}", result5);
}
fn main() {
// if表达式
let number = 7;
if number % 4 == 0 {
println!("{} 能被4整除", number);
} else if number % 3 == 0 {
println!("{} 能被3整除", number);
} else {
println!("{} 既不能被4整除也不能被3整除", number);
}
// if作为表达式
let condition = true;
let value = if condition { 5 } else { 6 };
println!("if表达式返回值: {}", value);
// 循环:loop
let mut count = 0;
let result = loop {
count += 1;
if count == 10 {
break count * 2; // 从循环中返回值
}
};
println!("loop循环结果: {}", result);
// 循环:while
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
println!("LIFTOFF!!!");
// 循环:for
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("数组元素: {}", element);
}
// for循环与范围
for number in 1..4 {
println!("范围循环: {}", number);
}
// 反向循环
for number in (1..4).rev() {
println!("反向循环: {}", number);
}
// match表达式
let coin = Coin::Quarter(UsState::Alabama);
let value = value_in_cents(coin);
println!("硬币价值: {} 美分", value);
// Option<T>的match
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
println!("plus_one(Some(5)) = {:?}", six);
println!("plus_one(None) = {:?}", none);
// if let语法糖
let config_max = Some(3u8);
if let Some(max) = config_max {
println!("配置最大值: {}", max);
}
// while let语法糖
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
stack.push(3);
while let Some(top) = stack.pop() {
println!("栈顶元素: {}", top);
}
// 标签循环
'outer: for x in 1..=3 {
for y in 1..=3 {
if x == 2 && y == 2 {
break 'outer; // 跳出外层循环
}
println!("x: {}, y: {}", x, y);
}
}
}
// 枚举定义
#[derive(Debug)]
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
#[derive(Debug)]
enum UsState {
Alabama,
Alaska,
// ... 其他州
}
// 枚举匹配函数
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!("来自 {:?} 州的25美分硬币!", state);
25
},
}
}
// Option<T>处理函数
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i + 1),
}
}
fn main() {
// ===================== 核心概念:栈/堆与变量地址 =====================
// 变量表(栈):程序运行时,变量名对应栈上的内存地址,存储"元数据"
// - 对于基本类型(标量)(5个:布尔、整数、浮点数、元组、字符(char),可以不移交所有权,下文继续用):栈上直接存储值本身
// - 对于复杂类型(对象)(String、Vec等):栈上存储「指针(指向堆地址)+ 长度 + 容量」,堆上存储实际数据
// 堆:动态分配的内存,生命周期由所有权系统管理
// 示例1:打印基本类型(栈上存储)的地址
let x = 5;
println!("基本类型x(i32)在栈上的地址: {:p}", &x); // {:p} 格式化输出指针地址
println!("x的值: {}(栈上直接存储)", x);
// 示例2:打印String类型的栈地址 + 堆数据地址
let s = String::from("hello");
println!("nString变量s在栈上的地址: {:p}", &s); // 栈上的变量地址(存储指针、长度、容量)
println!("s指向的堆数据起始地址: {:p}", s.as_ptr()); // 堆上实际字符串的地址
println!("s的长度: {},容量: {}", s.len(), s.capacity());
// ===================== 所有权规则演示 =====================
// 规则1:Rust中的每个值都有一个所有者
let s_owner = String::from("hello"); // s_owner是"hello"的所有者
println!("ns_owner = {}", s_owner);
// 规则2:值在任意时刻只能有一个所有者(所有权移动)
let s1 = String::from("hello");
println!("移动前:s1栈地址: {:p},堆地址: {:p}", &s1, s1.as_ptr());
let s2 = s1; // s1的所有权转移(Move)给s2:栈上的元数据(指针、长度、容量)被移动
// println!("s1 = {}", s1); // 编译错误:s1已失去所有权,变为"无效变量"
println!("移动后:s2栈地址: {:p},堆地址: {:p}", &s2, s2.as_ptr()); // 堆地址不变,仅栈上元数据转移
// ===================== 克隆(Clone):深拷贝 =====================
// 与Move的区别:Clone会复制栈上元数据 + 堆上实际数据,原变量仍有效
let s_clone_src = String::from("clone demo");
let s_clone_dst = s_clone_src.clone(); // 显式调用clone,深拷贝
println!("n克隆示例:");
println!("s_clone_src栈地址: {:p},堆地址: {:p}", &s_clone_src, s_clone_src.as_ptr());
println!("s_clone_dst栈地址: {:p},堆地址: {:p}", &s_clone_dst, s_clone_dst.as_ptr());
println!("s_clone_src = {}, s_clone_dst = {}", s_clone_src, s_clone_dst); // 两者都有效
// 规则3:当所有者离开作用域,值将被丢弃
{
let s_scope = String::from("scope");
println!("n作用域内: {}", s_scope);
} // s_scope离开作用域,Rust自动调用drop释放堆内存
// 基本类型的拷贝(Copy trait):栈上浅拷贝,原变量仍有效
let x_copy = 5;
let y_copy = x_copy; // 整数实现Copy,栈上直接拷贝值
println!("nx_copy = {}, y_copy = {}", x_copy, y_copy);
// ===================== 引用和借用 =====================
// 不可变引用:访问值但不获取所有权
let s_borrow = String::from("hello");
let len = calculate_length(&s_borrow); // &表示引用(借用)
println!("n字符串'{}'的长度是{}", s_borrow, len);
// 可变引用:修改值但不获取所有权
let mut s_mut = String::from("hello");
change(&mut s_mut); // &mut表示可变引用
println!("修改后的字符串: {}", s_mut);
// ===================== 切片 =====================
let s_slice = String::from("hello world");
let hello = &s_slice[0..5]; // 字符串切片(无所有权)
let world = &s_slice[6..11];
println!("n切片1: {}, 切片2: {}", hello, world);
// 数组切片
let a = [1, 2, 3, 4, 5];
let slice_arr = &a[1..3];
println!("数组切片: {:?}", slice_arr);
// ===================== 函数传递所有权 =====================
let s_fn = String::from("hello");
takes_ownership(s_fn);
// println!("s_fn = {}", s_fn); // 编译错误:所有权已转移
// 返回值转移所有权
let s1_fn = gives_ownership();
let s2_fn = String::from("hello");
let s3_fn = takes_and_gives_back(s2_fn);
println!("ns1_fn = {}, s3_fn = {}", s1_fn, s3_fn);
}
// 不可变引用函数:借用String,不获取所有权
fn calculate_length(s: &String) -> usize {
s.len()
}
// 可变引用函数:修改引用的值,不获取所有权
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
// 函数获取所有权
fn takes_ownership(some_string: String) {
println!("n获取所有权: {}", some_string);
}
// 函数返回所有权
fn gives_ownership() -> String {
let some_string = String::from("hello");
some_string
}
// 函数获取并返回所有权
fn takes_and_gives_back(a_string: String) -> String {
a_string
}
// 结构体定义
// 经典结构体(Classic Struct):包含命名字段的结构体
// 结构体字段可以是不同类型
struct User {
active: bool, // 布尔类型字段
username: String, // 字符串类型字段
email: String, // 字符串类型字段
sign_in_count: u64, // 无符号64位整数字段
}
// 元组结构体(Tuple Struct):类似于元组的结构体
// 字段没有名称,只有类型,使用索引访问
struct Color(i32, i32, i32); // 表示RGB颜色
struct Point(i32, i32, i32); // 表示三维坐标点
// 单元结构体(Unit Struct):没有任何字段的结构体
// 类似于单元类型(),但有自己的类型标识
struct UnitStruct;
// 结构体方法定义
// 结构体的方法在impl(implementation)块中定义
struct Rectangle {
width: u32, // 宽度
height: u32, // 高度
}
impl Rectangle {
// 关联函数(Associated Function)- 静态方法
// 关联函数不接收self参数,使用结构体名调用
// 通常用于创建结构体实例
fn square(size: u32) -> Rectangle {
Rectangle { width: size, height: size }
}
// 实例方法(Instance Method)
// 方法接收&self参数,表示对实例的不可变引用
// 用于访问实例的字段和行为
fn area(&self) -> u32 {
self.width * self.height // 计算矩形面积
}
// 带参数的方法
// 方法可以接收其他参数
fn can_hold(&self, other: &Rectangle) -> bool {
// 判断当前矩形是否能容纳另一个矩形
self.width > other.width && self.height > other.height
}
// 可变方法(Mutable Method)
// 方法接收&mut self参数,表示对实例的可变引用
// 可以修改实例的字段
fn double_size(&mut self) {
self.width *= 2; // 宽度加倍
self.height *= 2; // 高度加倍
}
}
// 结构体方法重载
// Rust不支持传统意义上的方法重载(同名方法不同参数)
// 但可以通过不同的方法名实现类似功能
struct Counter {
count: u32, // 计数器值
}
impl Counter {
// 构造函数(通常命名为new)
fn new() -> Counter {
Counter { count: 0 }
}
// 增加1的方法
fn increment(&mut self) {
self.count += 1;
}
// 增加指定数量的方法
fn increment_by(&mut self, amount: u32) {
self.count += amount;
}
// 获取当前值的方法
fn get_count(&self) -> u32 {
self.count
}
}
// 结构体组合
// 结构体可以包含其他结构体作为字段,实现组合
struct Address {
street: String, // 街道
city: String, // 城市
zip_code: String, // 邮政编码
}
struct Person {
name: String, // 姓名
age: u32, // 年龄
address: Address, // 地址(结构体字段)
}
impl Person {
// 构造函数
fn new(name: String, age: u32, address: Address) -> Person {
// 使用字段初始化简写语法
Person { name, age, address }
}
// 打印个人信息的方法
fn print_info(&self) {
}
}
fn main() {
// 创建结构体实例
// 使用结构体名和字段初始化语法
let user1 = User {
active: true,
username: String::from("someone123"),
email: String::from("someone@example.com"),
sign_in_count: 1,
};
// 注意这里没有mut,不可以直接更改,例如user1.active = xxx;
// 访问结构体字段
println!("用户名: {}", user1.username);
println!("邮箱: {}", user1.email);
// 结构体更新语法
// 使用..语法可以从其他实例复制字段
let user2 = User {
email: String::from("another@example.com"), // 新的邮箱地址
..user1 // 复制user1的其他字段
};
println!("user2 用户名: {}", user2.username); // 来自user1
println!("user2 邮箱: {}", user2.email); // 新的邮箱
// 元组结构体
// 元组结构体使用类似元组的语法创建
let black = Color(0, 0, 0); // 黑色
let origin = Point(0, 0, 0); // 原点坐标
// 访问元组结构体字段(使用索引)
println!("黑色RGB: {}, {}, {}", black.0, black.1, black.2);
println!("原点坐标: ({}, {}, {})", origin.0, origin.1, origin.2);
// 单元结构体
// 单元结构体没有字段,创建时不需要参数
let unit = UnitStruct;
// 结构体方法调用
// 实例方法使用点语法调用
let rect1 = Rectangle { width: 30, height: 50 };
println!("矩形面积: {}", rect1.area()); // 调用area方法
// 关联函数调用
// 关联函数使用::语法调用
let square = Rectangle::square(20); // 调用square关联函数
println!("正方形面积: {}", square.area());
// 方法参数
let rect2 = Rectangle { width: 10, height: 40 };
let rect3 = Rectangle { width: 60, height: 45 };
println!("rect1能容纳rect2吗? {}", rect1.can_hold(&rect2));
println!("rect1能容纳rect3吗? {}", rect1.can_hold(&rect3));
// 可变方法
// 要调用可变方法,实例必须是可变的
let mut rect4 = Rectangle { width: 5, height: 5 };
println!("修改前面积: {}", rect4.area());
rect4.double_size(); // 调用可变方法
println!("修改后面积: {}", rect4.area());
// 方法重载示例
let mut counter = Counter::new(); // 创建计数器
counter.increment(); // 增加1
counter.increment_by(5); // 增加5
println!("计数器值: {}", counter.get_count());
// 结构体组合
let address = Address {
street: String::from("123 Main St"),
city: String::from("Anytown"),
zip_code: String::from("12345"),
};
let person = Person::new(
String::from("John Doe"),
30,
address // address的所有权转移给person
);
person.print_info(); // 调用print_info方法
}
// 简单枚举
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) {
match self {
Message::Quit => println!("Quit message received"),
Message::Move { x, y } => println!("Move to ({}, {})", x, y),
Message::Write(text) => println!("Write message: {}", text),
Message::ChangeColor(r, g, b) => println!("Change color to RGB({}, {}, {})", r, g, b),
}
}
}
// Option枚举(标准库提供)
// enum Option<T> {
// Some(T),
// None,
// }
// 复杂枚举示例
enum WebEvent {
PageLoad,
PageUnload,
KeyPress(char),
Paste(String),
Click { x: i64, y: i64 },
}
// 模式匹配函数
fn inspect(event: WebEvent) {
match event {
WebEvent::PageLoad => println!("页面加载"),
WebEvent::PageUnload => println!("页面卸载"),
WebEvent::KeyPress(c) => println!("按键: '{}'" , c),
WebEvent::Paste(s) => println!("粘贴内容: {}", s),
WebEvent::Click { x, y } => println!("点击位置: ({}, {})", x, y),
}
}
// 枚举组合
enum Shape {
Circle(f64), // 半径
Rectangle(f64, f64), // 长和宽
Triangle(f64, f64, f64), // 三条边
}
impl Shape {
fn area(&self) -> f64 {
match self {
Shape::Circle(r) => std::f64::consts::PI r r,
Shape::Rectangle(w, h) => w * h,
Shape::Triangle(a, b, c) => {
// 使用海伦公式计算三角形面积
let s = (a + b + c) / 2.0;
(s (s - a) (s - b) * (s - c)).sqrt()
}
}
}
}
// if let 语法糖
fn handle_option(value: Option<i32>) {
if let Some(x) = value {
println!("获取到Some值: {}", x);
} else {
println!("获取到None值");
}
}
// while let 语法糖
fn process_values() {
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
stack.push(3);
while let Some(top) = stack.pop() {
println!("处理值: {}", top);
}
}
// 模式匹配中的通配符
fn match_with_wildcard(x: u8) {
match x {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
_ => println!("其他数字"), // 通配符
}
}
// 模式匹配中的范围
fn match_with_range(x: i32) {
match x {
1..=5 => println!("1到5之间"),
6..=10 => println!("6到10之间"),
_ => println!("超出范围"),
}
}
fn main() {
// 简单枚举使用
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
// 带数据的枚举
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
// 枚举方法调用
let quit_msg = Message::Quit;
let move_msg = Message::Move { x: 10, y: 20 };
let write_msg = Message::Write(String::from("Hello, Rust!"));
let color_msg = Message::ChangeColor(255, 0, 0);
quit_msg.call();
move_msg.call();
write_msg.call();
color_msg.call();
// Option枚举使用
// Option里要么有值Some, 要么为None
let some_number = Some(5);
let some_string = Some("a string");
let absent_number: Option<i32> = None;
println!("some_number: {:?}", some_number);
println!("some_string: {:?}", some_string);
println!("absent_number: {:?}", absent_number);
match some_number {
Some(x) => println!("Matched:{}", x),
None => println!("No value"),
}
// 复杂枚举模式匹配
let pressed = WebEvent::KeyPress('x');
let pasted = WebEvent::Paste("my text".to_owned());
let click = WebEvent::Click { x: 20, y: 80 };
inspect(pressed);
inspect(pasted);
inspect(click);
// 枚举组合计算
let circle = Shape::Circle(5.0);
let rectangle = Shape::Rectangle(10.0, 20.0);
let triangle = Shape::Triangle(3.0, 4.0, 5.0);
println!("圆形面积: {}", circle.area());
println!("矩形面积: {}", rectangle.area());
println!("三角形面积: {}", triangle.area());
// if let 使用
handle_option(Some(42));
handle_option(None);
// while let 使用
process_values();
// 通配符匹配
match_with_wildcard(3);
match_with_wildcard(5);
// 范围匹配
match_with_range(3);
match_with_range(8);
match_with_range(15);
}
use std::collections::{HashMap, HashSet, BTreeMap, BTreeSet};
fn main() {
// Vector(动态数组)
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
println!("Vector: {:?}", v);
println!("Vector长度: {}", v.len());
println!("Vector容量: {}", v.capacity());
// 访问Vector元素
let first = &v[0];
println!("第一个元素: {}", first);
match v.get(1) {
Some(second) => println!("第二个元素: {}", second),
None => println!("没有第二个元素"),
}
// 遍历Vector
println!("遍历Vector:");
for i in &v {
println!("{}", i);
}
// 修改遍历中的元素
for i in &mut v {
i = 2;
}
println!("修改后的Vector: {:?}", v);
// String(字符串)
let mut s = String::new();
s.push_str("Hello");
s.push(' ');
s.push_str("World!");
println!("nString: {}", s);
println!("字符串长度: {}", s.len());
println!("是否为空: {}", s.is_empty());
// 字符串拼接
let s1 = String::from("Hello, ");
let s2 = String::from("Rust!");
let s3 = s1 + &s2; // s1的所有权被移动,不能再使用
println!("拼接后的字符串: {}", s3);
// 格式化字符串
let name = "Alice";
let age = 30;
let formatted = format!("姓名: {}, 年龄: {}", name, age);
println!("格式化字符串: {}", formatted);
// 字符串切片
let hello = "Здравствуйте";
let s = &hello[0..4];
println!("字符串切片: {}", s);
// HashMap(哈希映射)
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10); // k, v
scores.insert(String::from("Yellow"), 50); // k, v
println!("nHashMap: {:?}", scores);
// 访问HashMap值
let team_name = String::from("Blue");
let score = scores.get(&team_name);
match score {
Some(s) => println!("Blue队得分: {}", s),
None => println!("没有找到Blue队"),
}
// 遍历HashMap
println!("遍历HashMap:");
for (key, value) in &scores {
println!("{}: {}", key, value);
}
// 更新HashMap
scores.insert(String::from("Blue"), 25); // 覆盖值
println!("更新后的HashMap: {:?}", scores);
// 只在键不存在时插入
scores.entry(String::from("Red")).or_insert(30);
scores.entry(String::from("Blue")).or_insert(50);
println!("插入后的HashMap: {:?}", scores);
// HashSet(哈希集合)
let mut set = HashSet::new();
set.insert(1);
set.insert(2);
set.insert(3);
set.insert(2); // 重复元素不会被插入
println!("nHashSet: {:?}", set);
println!("集合大小: {}", set.len());
println!("是否包含2: {}", set.contains(&2));
// 集合操作
let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
let b: HashSet<_> = vec![2, 3, 4].into_iter().collect();
println!("交集: {:?}", a.intersection(&b));
println!("并集: {:?}", a.union(&b));
println!("差集: {:?}", a.difference(&b));
// BTreeMap(有序映射)
let mut tree_map = BTreeMap::new();
tree_map.insert(3, "three");
tree_map.insert(1, "one");
tree_map.insert(2, "two");
println!("nBTreeMap: {:?}", tree_map);
// BTreeSet(有序集合)
let mut tree_set = BTreeSet::new();
tree_set.insert(3);
tree_set.insert(1);
tree_set.insert(2);
println!("BTreeSet: {:?}", tree_set);
// 更多集合操作
let mut v = vec![1, 2, 3, 4, 5];
// 排序
v.sort();
println!("n排序后的Vector: {:?}", v);
// 反转
v.reverse();
println!("反转后的Vector: {:?}", v);
// 过滤
let filtered: Vec<_> = v.iter().filter(|&&x| x > 2).collect();
println!("过滤后的Vector: {:?}", filtered);
// 映射
let mapped: Vec<_> = v.iter().map(|&x| x * 2).collect();
println!("映射后的Vector: {:?}", mapped);
// 求和
let sum: i32 = v.iter().sum();
println!("Vector元素总和: {}", sum);
}
// 声明模块
mod front_of_house {
// 嵌套模块
pub mod hosting {
pub fn add_to_waitlist() {
println!("添加到等待列表");
}
fn seat_at_table() {
println!("安排座位");
}
}
// 嵌套模块
mod serving {
pub fn take_order() {
println!("接受订单");
}
pub fn serve_order() {
println!("提供服务");
}
pub fn take_payment() {
println!("收款");
}
}
}
// 导入模块
use crate::front_of_house::hosting; // 试用这个里面的 这个模块...
use crate::front_of_house::serving::{serve_order, take_payment}; // 使用这个模块里的这个模块里的 这个和这个方法。
// 嵌套模块
mod back_of_house {
pub struct Breakfast {
pub toast: String,
seasonal_fruit: String,
}
impl Breakfast {
pub fn summer(toast: &str) -> Breakfast {
Breakfast {
toast: String::from(toast),
seasonal_fruit: String::from("桃子"),
}
}
}
mod kitchen {
pub fn cook_order() {
println!("烹饪订单");
}
}
}
use crate::back_of_house::Breakfast;
use crate::back_of_house::kitchen;
// 外部包导入示例
// extern crate rand;
// use rand::Rng;
// 模块路径
fn deliver_order() {
// 绝对路径
crate::front_of_house::hosting::add_to_waitlist();
// 相对路径
front_of_house::serving::take_order();
}
fn main() {
println!("=== 包和模块示例 ===n");
// 使用导入的模块
hosting::add_to_waitlist();
serve_order();
take_payment();
// 使用结构体
let mut meal = Breakfast::summer("全麦");
println!("n早餐吐司: {}", meal.toast);
// println!("季节水果: {}", meal.seasonal_fruit); // 这会导致编译错误,因为seasonal_fruit是私有的
// 修改公共字段
meal.toast = String::from("白面包");
println!("修改后的吐司: {}", meal.toast);
// 使用嵌套模块
kitchen::cook_order();
// 使用模块路径
deliver_order();
// 包结构说明
println!("n=== 包结构说明 ===");
println!("Rust包结构:");
println!("my_crate/");
println!("├── Cargo.toml");
println!("├── Cargo.lock");
println!("└── src/");
println!(" ├── lib.rs # 库包的根文件");
println!(" ├── main.rs # 二进制包的根文件");
println!(" ├── module1.rs # 模块文件");
println!(" └── module2/ # 模块目录");
println!(" └── mod.rs # 模块目录的根文件");
// 模块可见性规则
println!("n=== 模块可见性规则 ===");
println!("1. 默认情况下,模块中的项是私有的");
println!("2. 使用pub关键字可以将项设为公共的");
println!("3. 子模块可以访问父模块中的项");
println!("4. 父模块不能访问子模块中的私有项");
println!("5. 使用use关键字可以简化模块路径");
}
// 模块文件导入示例(注释掉的代码展示如何导入其他文件中的模块)
// mod module1; // 导入module1.rs文件
// mod module2; // 导入module2/mod.rs文件
use std::fs::File;
use std::io::{self, Read};
use std::num::ParseIntError;
// Result枚举定义(标准库提供)
// enum Result<T, E> {
// Ok(T),
// Err(E),
// }
// 简单错误处理
fn read_username_from_file() -> Result<String, io::Error> {
}
// 更简洁的版本
fn read_username_short() -> Result<String, io::Error> {
fs::read_to_string("hello.txt")
}
// 错误传播
fn parse_number(s: &str) -> Result<i32, ParseIntError> {
s.parse::<i32>()
}
// 组合多个错误
fn multiply_two_numbers(s1: &str, s2: &str) -> Result<i32, ParseIntError> {
let n1 = s1.parse::<i32>()?;
let n2 = s2.parse::<i32>()?;
Ok(n1 * n2)
}
// 自定义错误类型
#[derive(Debug)]
enum CustomError {
IoError(io::Error),
ParseError(ParseIntError),
InvalidInput(String),
}
impl From<io::Error> for CustomError {
fn from(err: io::Error) -> Self {
CustomError::IoError(err)
}
}
impl From<ParseIntError> for CustomError {
fn from(err: ParseIntError) -> Self {
CustomError::ParseError(err)
}
}
// 如果有 内容,则返回一个空的OK , 如果没有,则返回错误
fn complex_operation() -> Result<(), CustomError> {
let mut file = File::open("data.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let number: i32 = contents.trim().parse()?;
if number < 0 {
return Err(CustomError::InvalidInput(
"数字不能为负数".to_string()
));
}
Ok(())
}
// panic!宏(不可恢复错误)
fn panic_example() {
// 故意触发panic
let v = vec![1, 2, 3];
v[99]; // 索引越界,触发panic
}
// 错误处理策略
fn error_handling_strategies() {
// 1. 传播错误(最常见)
let result = read_username_from_file();
match result {
Ok(username) => println!("用户名: {}", username),
Err(e) => println!("读取文件失败: {}", e),
}
// 2. 匹配不同的错误类型
let file_result = File::open("hello.txt");
match file_result {
Ok(file) => println!("文件打开成功"),
Err(error) => match error.kind() {
io::ErrorKind::NotFound => println!("文件未找到"),
io::ErrorKind::PermissionDenied => println!("权限不足"),
_ => println!("其他错误: {}", error),
},
}
// 3. 使用unwrap和expect(快速原型开发)
let file = File::open("hello.txt").unwrap(); // 这里使用了unwrap如果失败则发生panic(崩溃)
let file = File::open("hello.txt")
.expect("打开hello.txt文件失败"); // 提供自定义panic消息
// 4. 静默失败(不推荐)
let _ = File::open("hello.txt");
}
// 错误链
fn error_chain() -> Result<(), Box<dyn std::error::Error>> {
let mut file = File::open("chain.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let number: i32 = contents.trim().parse()?;
println!("读取的数字: {}", number);
Ok(())
}
fn main() {
println!("=== Rust错误处理示例 ===n");
// 简单错误处理 (可恢复错误)
match read_username_from_file() {
Ok(username) => println!("读取到的用户名: {}", username),
Err(e) => println!("读取文件错误: {}", e),
}
// 数字解析错误处理
let result = multiply_two_numbers("42", "2");
match result {
Ok(product) => println!("乘法结果: {}", product),
Err(e) => println!("解析错误: {}", e),
}
let result = multiply_two_numbers("42", "abc");
match result {
Ok(product) => println!("乘法结果: {}", product),
Err(e) => println!("解析错误: {}", e),
}
// 自定义错误类型
match complex_operation() {
Ok(()) => println!("复杂操作成功"),
Err(e) => println!("复杂操作失败: {:?}", e),
}
// 错误链
match error_chain() {
Ok(()) => println!("错误链操作成功"),
Err(e) => println!("错误链操作失败: {}", e),
}
// 错误处理总结
println!("n=== 错误处理总结 ===");
println!("1. Result<T, E> 用于可恢复错误");
println!("2. panic! 用于不可恢复错误");
println!("3. ? 操作符用于传播错误");
println!("4. 可以定义自定义错误类型");
println!("5. 错误处理策略包括:传播、匹配、unwrap/expect、静默失败");
}
// 泛型函数
fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
let mut largest = list[0];
for &item in list.iter() {
if item > largest {
largest = item;
}
}
largest
}
// 泛型结构体
struct Point<T> {
x: T;
y: T,
}
// 为泛型结构体实现方法
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
fn y(&self) -> &T {
&self.y
}
}
// 为特定类型实现方法
impl Point<f32> {
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}
// 多参数泛型结构体
struct Pair<T, U> {
x: T,
y: U,
}
impl<T, U> Pair<T, U> {
fn new(x: T, y: U) -> Self {
Pair { x, y }
}
fn components(&self) -> (&T, &U) {
(&self.x, &self.y)
}
}
// 泛型枚举
enum Option<T> {
Some(T),
None,
}
enum Result<T, E> {
Ok(T),
Err(E),
}
// 泛型约束
fn print_if_display<T: std::fmt::Display>(item: T) {
println!("{}", item);
}
// 多重约束
fn compare_and_print<T: std::fmt::Display + PartialOrd>(a: T, b: T) {
if a > b {
println!("{} 大于 {}", a, b);
} else if a < b {
println!("{} 小于 {}", a, b);
} else {
println!("{} 等于 {}", a, b);
}
}
// where子句(更清晰的约束语法)
fn some_function<T, U>(t: T, u: U) -> i32
where
T: std::fmt::Display + Clone,
U: std::fmt::Debug + Clone,
{
println!("T: {}, U: {:?}", t, u);
42
}
// 泛型返回类型
fn identity<T>(x: T) -> T {
x
}
// 泛型集合操作
fn find_first<T: PartialEq>(list: &[T], target: &T) -> Option<usize> {
for (index, item) in list.iter().enumerate() {
if item == target {
return Some(index);
}
}
None
}
fn main() {
println!("=== Rust泛型示例 ===n");
// 泛型函数使用
let numbers = vec![34, 50, 25, 100, 65];
let result = largest(&numbers);
println!("最大的数字: {}", result);
let chars = vec!['y', 'm', 'a', 'q'];
let result = largest(&chars);
println!("最大的字符: {}", result);
// 泛型结构体
let integer_point = Point { x: 5, y: 10 };
let float_point = Point { x: 1.0, y: 4.0 };
println!("n整数点: ({}, {})", integer_point.x(), integer_point.y());
println!("浮点点点: ({}, {})", float_point.x(), float_point.y());
println!("浮点点距离原点: {}", float_point.distance_from_origin());
// 多参数泛型
let pair = Pair::new(10, "hello");
let (x, y) = pair.components();
println!("nPair: x={}, y={}", x, y);
// 泛型约束
print_if_display(42);
print_if_display("hello");
// print_if_display(true); // 错误,bool不实现Display trait
compare_and_print(10, 20);
compare_and_print(3.14, 2.71);
compare_and_print("apple", "banana");
// where子句
some_function(42, "hello");
// 泛型返回类型
let num = identity(42);
let text = identity("hello");
println!("nidentity(42) = {}", num);
println!("identity("hello") = {}", text);
// 泛型集合操作
let numbers = vec![1, 2, 3, 4, 5];
let index = find_first(&numbers, &3);
println!("n查找3的位置: {:?}", index);
let fruits = vec!["apple", "banana", "cherry"];
let index = find_first(&fruits, &"banana");
println!("查找"banana"的位置: {:?}", index);
// 泛型总结
println!("n=== 泛型总结 ===");
println!("1. 泛型允许编写不特定于具体类型的代码");
println!("2. 泛型使用<T>语法定义类型参数");
println!("3. 可以为泛型类型添加约束(trait bounds)");
println!("4. where子句提供更清晰的约束语法");
println!("5. 泛型在编译时会进行单态化,不影响运行时性能");
println!("6. 标准库广泛使用泛型:Vec<T>, Option<T>, Result<T, E>等");
}
// 12_traits_detailed.rs - Rust Trait详解(详细注释版)
// Trait定义
// Trait(特征)是Rust中定义共享行为的方式,类似于其他语言中的接口(Interface)
// Trait定义了一组方法的签名,类型可以实现这些方法来提供特定的行为
trait Summary {
// 抽象方法(Abstract Method)
// 没有默认实现的方法,实现Trait的类型必须提供具体实现
fn summarize(&self) -> String;
// 默认实现方法(Default Method Implementation)
// 提供了默认实现的方法,实现Trait的类型可以选择覆盖或使用默认实现
fn summarize_author(&self) -> String {
String::from("Unknown author") // 默认返回"Unknown author"
}
// 调用其他方法的默认方法
// 默认方法可以调用Trait中的其他方法,包括抽象方法
fn summarize_with_author(&self) -> String {
format!("{} - {}", self.summarize(), self.summarize_author())
}
}
// 为类型实现Trait
// 结构体定义 - 新闻文章
struct NewsArticle {
headline: String, // 标题
location: String, // 位置
author: String, // 作者
content: String, // 内容
}
// 为NewsArticle实现Summary Trait
// 使用impl关键字,后面跟Trait名称,然后是for关键字和类型名称
impl Summary for NewsArticle {
// 实现抽象方法summarize
// 必须提供具体实现,因为Trait中没有默认实现
fn summarize(&self) -> String {
format!("{}, by {} ({})", self.headline, self.author, self.location)
}
// 覆盖默认方法summarize_author
// 可以选择覆盖默认方法,提供自定义实现
fn summarize_author(&self) -> String {
format!("@{}", self.author) // 返回带有@符号的作者名
}
}
// 结构体定义 - 推文
struct Tweet {
username: String, // 用户名
content: String, // 内容
reply: bool, // 是否是回复
retweet: bool, // 是否是转发
}
// 为Tweet实现Summary Trait
impl Summary for Tweet {
// 只实现抽象方法summarize,使用默认的summarize_author
// 对于有默认实现的方法,可以选择不覆盖
fn summarize(&self) -> String {
format!("{}: {}", self.username, self.content)
}
}
// Trait作为参数
// 使用impl Trait语法,函数可以接受任何实现了指定Trait的类型
// 这是一种语法糖,等价于泛型Trait约束
fn notify(item: &impl Summary) {
println!("Breaking news! {}", item.summarize());
}
// Trait约束语法(Trait Bound Syntax)
// 与impl Trait语法等价,但更明确地使用泛型参数
// 当需要在多个地方引用相同的泛型类型时,这种语法更有用
fn notify_with_constraint<T: Summary>(item: &T) {
println!("Breaking news! {}", item.summarize());
}
// 多个Trait约束
// 可以指定类型需要实现多个Trait,使用+符号分隔
fn notify_multiple<T: Summary + std::fmt::Display>(item: &T) {
println!("News: {} - {}", item, item.summarize());
}
// where子句(Where Clause)
// 当有多个泛型参数和Trait约束时,where子句提供更清晰的语法
// 特别是当约束比较复杂时,where子句比在函数签名中使用+符号更易读
fn some_function<T, U>(t: &T, u: &U) -> i32
where
T: Summary + Clone, // T需要实现Summary和Clone Trait
U: std::fmt::Debug + Clone, // U需要实现Debug和Clone Trait
{
println!("T: {}", t.summarize());
println!("U: {:?}", u);
42 // 返回一个整数
}
// Trait作为返回类型
// 函数可以返回实现了指定Trait的类型,使用impl Trait语法
// 注意:这种语法只能返回一种具体类型,即使有多个类型实现了相同的Trait
fn returns_summarizable() -> impl Summary {
Tweet {
username: String::from("horse_ebooks"),
content: String::from("of course, as you probably already know, people"),
reply: false,
retweet: false,
}
}
// 条件实现方法(Conditional Implementation)
// 可以为满足特定Trait约束的泛型类型实现方法
struct Pair<T> {
x: T,
y: T,
}
// 为所有Pair<T>实现new方法
// 这个实现对任何类型T都有效
impl<T> Pair<T> {
fn new(x: T, y: T) -> Self {
Pair { x, y }
}
}
// 只为实现了Display和PartialOrd的Pair<T>实现cmp_display方法
// 这个实现只对满足Trait约束的类型T有效
impl<T: std::fmt::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);
}
}
}
// 为其他类型实现Trait(孤儿规则)
// 孤儿规则(Orphan Rule):只能为本地类型实现外部Trait,或者为外部类型实现本地Trait
// 这里为Tweet实现标准库的Display Trait
impl std::fmt::Display for Tweet {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}: {}", self.username, self.content)
}
}
// 派生Trait(Derived Trait)
// 使用#[derive]属性可以自动实现一些标准Trait
// 可以派生的Trait包括:Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy等
#[derive(Debug, PartialEq, Clone)]
struct Point {
x: i32,
y: i32,
}
// 运算符Trait(Operator Trait)
// 标准库提供了一系列运算符Trait,实现这些Trait可以重载运算符
use std::ops::Add;
// 为Point实现Add Trait,重载+运算符
impl Add for Point {
type Output = Point; // 关联类型,指定加法的输出类型
fn add(self, other: Point) -> Point {
Point {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
// 关联类型(Associated Types)
// Trait可以定义关联类型,关联类型是Trait定义的一部分
// 关联类型指定了Trait中某些方法会使用的类型
trait Iterator {
type Item; // 关联类型,指定迭代器产生的元素类型
fn next(&mut self) -> Option<Self::Item>;
}
struct Counter {
count: u32,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}
// 为Counter实现Iterator Trait
impl Iterator for Counter {
type Item = u32; // 指定关联类型为u32
fn next(&mut self) -> Option<Self::Item> {
if self.count < 5 {
self.count += 1;
Some(self.count)
} else {
None
}
}
}
fn main() {
println!("=== Rust Trait示例 ===n");
// Trait实现
let tweet = Tweet {
username: String::from("horse_ebooks"),
content: String::from("of course, as you probably already know, people"),
reply: false,
retweet: false,
};
let article = NewsArticle {
headline: String::from("Penguins win the Stanley Cup Championship!"),
location: String::from("Pittsburgh, PA, USA"),
author: String::from("Iceburgh"),
content: String::from("The Pittsburgh Penguins once again are the best\
hockey team in the NHL."),
};
println!("Tweet summary: {}", tweet.summarize());
println!("Article summary: {}", article.summarize());
println!("Tweet with author: {}", tweet.summarize_with_author());
println!("Article with author: {}", article.summarize_with_author());
// Trait作为参数
notify(&tweet);
notify(&article);
// 多个Trait约束
notify_multiple(&tweet);
// Trait作为返回类型
let item = returns_summarizable();
println!("n返回的Trait对象: {}", item.summarize());
// 条件实现方法
let pair = Pair::new(1, 2);
pair.cmp_display();
// 派生Trait
let p1 = Point { x: 1, y: 2 };
let p2 = Point { x: 1, y: 2 };
let p3 = Point { x: 3, y: 4 };
println!("nPoint p1: {:?}", p1); // 使用Debug Trait
println!("p1 == p2: {}", p1 == p2); // 使用PartialEq Trait
println!("p1 == p3: {}", p1 == p3);
// 运算符Trait
let p4 = p1 + p2; // 使用Add Trait
println!("p1 + p2 = {:?}", p4);
// 关联类型
let mut counter = Counter::new();
println!("nCounter迭代:");
while let Some(count) = counter.next() { // 使用Iterator Trait
println!("{}", count);
}
// Trait总结
println!("n=== Trait总结 ===");
println!("1. Trait定义共享行为");
println!("2. 可以为类型实现Trait");
println!("3. Trait可以作为参数和返回类型");
println!("4. 支持多个Trait约束");
println!("5. 支持条件实现方法");
println!("6. 可以派生标准Trait");
println!("7. 支持运算符重载");
println!("8. 有关联类型的Trait");
}
// 简单生命周期示例
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
// 生命周期省略规则
// 规则1:每个参数的生命周期成为独立的生命周期参数
// 规则2:如果只有一个输入生命周期参数,它被赋予所有输出生命周期参数
// 规则3:如果有多个输入生命周期参数,且其中一个是&self或&mut self,
// 那么self的生命周期被赋予所有输出生命周期参数
// 结构体中的生命周期
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
}
}
// 静态生命周期
fn static_lifetime() {
let s: &'static str = "I have a static lifetime.";
println!("静态字符串: {}", s);
}
// 多个生命周期参数
fn longest_with_an_announcement<'a, T>(
x: &'a str,
y: &'a str,
ann: T,
) -> &'a str
where
T: std::fmt::Display,
{
println!("Announcement! {}", ann);
if x.len() > y.len() {
x
} else {
y
}
}
// 生命周期与泛型和Trait结合
fn complex_function<'a, T>(x: &'a T, y: &'a T) -> &'a T
where
T: std::fmt::Display + PartialOrd,
{
if x > y {
x
} else {
y
}
}
// 生命周期边界
fn lifetime_bounds<'a, T: 'a>(x: &'a T) -> &'a T {
x
}
// 省略生命周期的常见模式
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[..]
}
// 结构体中的多个生命周期
struct MultiLifetime<'a, 'b> {
part1: &'a str,
part2: &'b str,
}
// 生命周期与闭包
fn lifetime_with_closure() {
let x = 5;
let equal_to_x = |z: i32| z == x;
let y = 5;
assert!(equal_to_x(y));
}
fn main() {
println!("=== Rust生命周期示例 ===n");
// 简单生命周期函数
let string1 = String::from("abcd");
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
println!("较长的字符串: {}", result);
// 结构体中的生命周期
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentence = novel.split('.').next().expect("Could not find a '.'");
let i = ImportantExcerpt {
part: first_sentence,
};
println!("n结构体中的引用: {}", i.part);
println!("方法返回的引用: {}", i.announce_and_return_part("Listen!"));
// 静态生命周期
static_lifetime();
// 多个生命周期参数
let string3 = String::from("long string is long");
let result = longest_with_an_announcement(
);
println!("n带公告的较长字符串: {}", result);
// 省略生命周期的函数
let s = String::from("hello world");
let word = first_word(&s);
println!("n第一个单词: {}", word);
// 结构体中的多个生命周期
let s1 = String::from("part1");
let s2 = String::from("part2");
let multi = MultiLifetime {
part1: &s1,
part2: &s2,
};
println!("n多个生命周期: part1={}, part2={}", multi.part1, multi.part2);
// 生命周期总结
println!("n=== 生命周期总结 ===");
println!("1. 生命周期确保引用总是有效的");
println!("2. 使用'<'和'>'定义生命周期参数");
println!("3. 有三条生命周期省略规则");
println!("4. 结构体可以包含引用,需要指定生命周期");
println!("5. 'static生命周期表示整个程序期间都有效");
println!("6. 可以有多个生命周期参数");
println!("7. 生命周期可以与泛型和Trait结合使用");
println!("8. 闭包会自动捕获环境的生命周期");
}
use std::fmt;
use std::fs::File;
use std::io::{self, BufRead, Write};
use std::collections::HashMap;
// 定义Trait
trait Printable {
fn print(&self) -> String;
}
// 定义枚举
enum LogLevel {
Info,
Warning,
Error,
}
impl fmt::Display for LogLevel {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
LogLevel::Info => write!(f, "INFO"),
LogLevel::Warning => write!(f, "WARNING"),
LogLevel::Error => write!(f, "ERROR"),
}
}
}
// 定义结构体
struct Logger {
name: String,
level: LogLevel,
messages: Vec<String>,
}
impl Logger {
// 关联函数
fn new(name: &str, level: LogLevel) -> Self {
Logger {
}
}
// 方法
fn log(&mut self, level: LogLevel, message: &str) {
let log_message = format!(
"[{}] [{}] {}",
self.name, level, message
);
self.messages.push(log_message.clone());
println!("{}", log_message);
}
// 泛型方法
fn log_formatted<T: fmt::Display>(&mut self, level: LogLevel, message: T) {
self.log(level, &message.to_string());
}
// 保存日志到文件
fn save_to_file(&self, filename: &str) -> io::Result<()> {
let mut file = File::create(filename)?;
for message in &self.messages {
writeln!(file, "{}", message)?;
}
Ok(())
}
}
// 为Logger实现Printable Trait
impl Printable for Logger {
fn print(&self) -> String {
format!(
"Logger: {}, Level: {}, Messages: {}",
self.name, self.level, self.messages.len()
)
}
}
// 错误处理函数
fn process_file(filename: &str) -> Result<Vec<String>, io::Error> {
let file = File::open(filename)?;
let reader = io::BufReader::new(file);
let mut lines = Vec::new();
for line in reader.lines() {
lines.push(line?);
}
Ok(lines)
}
// 泛型函数
fn find_max<T: PartialOrd + Copy>(list: &[T]) -> Option<T> {
if list.is_empty() {
return None;
}
let mut max = list[0];
for &item in list.iter() {
if item > max {
max = item;
}
}
Some(max)
}
// 生命周期函数
fn longest_with_prefix<'a>(s1: &'a str, s2: &'a str, prefix: &str) -> &'a str {
if s1.starts_with(prefix) && s1.len() > s2.len() {
s1
} else if s2.starts_with(prefix) {
s2
} else {
if s1.len() > s2.len() {
s1
} else {
s2
}
}
}
// 主函数
fn main() -> io::Result<()> {
println!("=== Rust综合示例 ===n");
// 1. 枚举和结构体使用
let mut logger = Logger::new("app_logger", LogLevel::Info);
logger.log(LogLevel::Info, "应用程序启动");
logger.log(LogLevel::Warning, "内存使用过高");
logger.log(LogLevel::Error, "数据库连接失败");
// 2. 泛型方法
logger.log_formatted(LogLevel::Info, 42);
logger.log_formatted(LogLevel::Info, 3.14159);
// 3. Trait实现
println!("n{}", logger.print());
// 4. 错误处理
match process_file("log.txt") {
Ok(lines) => println!("读取到 {} 行日志", lines.len()),
Err(e) => println!("读取文件失败: {}", e),
}
// 5. 泛型函数
let numbers = vec![1, 3, 5, 2, 4];
if let Some(max) = find_max(&numbers) {
println!("n最大值: {}", max);
}
let floats = vec![1.1, 2.2, 0.5, 3.3];
if let Some(max) = find_max(&floats) {
println!("浮点数最大值: {}", max);
}
// 6. 生命周期
let s1 = String::from("hello world");
let s2 = String::from("hello rust");
let longest = longest_with_prefix(&s1, &s2, "hello");
println!("n最长字符串: {}", longest);
// 7. 集合操作
let mut map = HashMap::new();
map.insert("info", 1);
map.insert("warning", 1);
map.insert("error", 1);
println!("n日志统计:");
for (level, count) in map {
println!("{}: {}", level, count);
}
// 8. 保存日志到文件
logger.save_to_file("application.log")?;
println!("n日志已保存到文件");
Ok(())
}
- 作者:L_Z_J
- 链接:https://www.mcoi.top/article/Post-rust-basic-syntax-notes
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。








