This commit is contained in:
e2hang
2025-10-05 23:51:24 +08:00
parent 1f9543c16c
commit 23f17bfc2c
113 changed files with 1236 additions and 0 deletions

290
Common-Use/readme.md Normal file
View File

@@ -0,0 +1,290 @@
非常好的问题 👏
`Option<&V>` 是 Rust 中非常核心的类型之一,理解它对你掌握 **Rust 的所有权系统****安全编程哲学** 都至关重要。
我们来一步步深入讲清楚,从原理到底层实现、再到各种用法与技巧。
---
# 🧩 一、什么是 `Option<T>`
## ✅ 定义
`Option<T>` 是一个**枚举类型**,定义在标准库中:
```rust
enum Option<T> {
Some(T),
None,
}
```
也就是说,它是一个「可能有值,也可能没有值」的容器。
* `Some(T)` 表示存在一个值;
* `None` 表示值不存在。
---
## 🧠 为什么要有 `Option<T>`
在很多语言(如 C/C++、Java缺失值通常用 `NULL``None`,但容易出错。
Rust 用 `Option<T>` 代替「空指针」,**在类型层面上强制你处理缺失的情况**。
这样编译器就能帮你防止空指针错误(`null pointer dereference`)。
---
# 🔍 二、`Option<&V>` 是什么?
`HashMap::get()` 等函数中,你会看到返回类型是:
```rust
Option<&V>
```
意思是:
> “可能返回一个指向值 `V` 的引用,如果 key 不存在,则返回 None。”
举个例子:
```rust
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("apple", 3);
let v1 = map.get("apple"); // Some(&3)
let v2 = map.get("banana"); // None
println!("{:?} {:?}", v1, v2);
}
```
输出:
```
Some(3) None
```
---
# 🧩 三、匹配(模式匹配)方式
最常见的处理方式是 **match**
```rust
match map.get("apple") {
Some(value) => println!("Found: {}", value),
None => println!("Not found"),
}
```
这种写法非常直观,但略显冗长,于是 Rust 提供了更优雅的写法👇
---
# ⚙️ 四、常见用法大全
## 1⃣ `is_some()` / `is_none()`
判断是否存在值:
```rust
if map.get("apple").is_some() {
println!("存在 apple");
}
```
---
## 2⃣ `unwrap()` / `unwrap_or()` / `unwrap_or_default()`
提取值:
```rust
let v = map.get("apple").unwrap(); // 若 None 则 panic!
let v = map.get("apple").unwrap_or(&0); // 若 None 则返回 &0
let v = map.get("apple").unwrap_or_default(); // 若 None 则返回默认值
```
> ⚠️ 不建议随意使用 `unwrap()`,除非你确信一定有值。
---
## 3⃣ `if let` 简写匹配
```rust
if let Some(v) = map.get("apple") {
println!("数量: {}", v);
}
```
`match` 简洁,常用于只关心 `Some` 的情况。
---
## 4⃣ `map()` —— 映射转换
`map()` 能把 `Option` 内的值加工成另一个类型:
```rust
let length = map.get("apple").map(|v| v * 2);
println!("{:?}", length); // Some(6)
```
若为 `None`,则结果仍是 `None`
---
## 5⃣ `and_then()` —— 链式调用
用于多层 Option 嵌套场景:
```rust
let result = map.get("apple")
.and_then(|v| Some(v * 10))
.and_then(|x| Some(x + 1));
println!("{:?}", result); // Some(31)
```
---
## 6⃣ `unwrap_or_else()` —— 延迟计算默认值
```rust
let v = map.get("banana").unwrap_or_else(|| {
println!("key 不存在,使用默认值");
&0
});
```
如果 key 不存在,执行闭包生成默认值。
---
## 7⃣ `as_ref()` / `as_mut()`
`Option<T>` 转换为 `Option<&T>``Option<&mut T>`
```rust
let opt = Some(String::from("hi"));
let ref_opt = opt.as_ref(); // Option<&String>
let mut_opt = opt.as_ref(); // Option<&mut String>
```
这在借用时非常实用,尤其是嵌套结构。
---
## 8⃣ `expect()` —— 自定义 panic 信息
```rust
let v = map.get("apple").expect("apple 不存在!");
```
如果是 `None`,会 panic 并显示 `"apple 不存在!"`
---
## 9⃣ `copied()` / `cloned()`
如果你要从 `Option<&T>` 提取出 `Option<T>`(复制/克隆),可以这样:
```rust
let map = HashMap::from([("a", 10)]);
let val = map.get("a").copied(); // Option<i32>
println!("{:?}", val); // Some(10)
```
区别:
* `.copied()` 要求 `T: Copy`
* `.cloned()` 要求 `T: Clone`
---
## 🔟 `unwrap_or_default()`
对简单类型(如 `i32``bool`)非常方便:
```rust
let map = HashMap::new();
let v: i32 = *map.get("x").unwrap_or_default(); // None -> 默认0
```
---
# 🧠 五、内部机制(零成本抽象)
Rust 的 `Option<T>` 在底层通常会被 **编译器优化为“无额外开销”** 的形式。
举个例子:
`Option<&T>` 通常和 `*const T` 的大小完全一样。
因为:
* `None` 会用空指针 `0` 表示;
* `Some(x)` 则用非零指针。
所以:
```rust
std::mem::size_of::<Option<&i32>>() == std::mem::size_of::<&i32>()
```
✅ 成立,说明 `Option<&T>` 没有额外开销。
---
# 🧩 六、总结表格
| 方法 | 作用 | 示例 | | |
| --------------------- | -------------------------------- | ------------------------- | - | ----------- |
| `is_some()` | 是否有值 | `opt.is_some()` | | |
| `is_none()` | 是否为空 | `opt.is_none()` | | |
| `unwrap()` | 直接取值(危险) | `opt.unwrap()` | | |
| `unwrap_or(x)` | 无值时返回 x | `opt.unwrap_or(0)` | | |
| `unwrap_or_default()` | 无值时返回默认值 | `opt.unwrap_or_default()` | | |
| `unwrap_or_else(f)` | 无值时调用函数生成 | `opt.unwrap_or_else( | | 0)` |
| `expect(msg)` | 无值时 panic带信息 | `opt.expect("错误")` | | |
| `map(f)` | 处理 Some 中的值 | `opt.map( | x | x+1)` |
| `and_then(f)` | 链式 Option 处理 | `opt.and_then( | x | Some(x+1))` |
| `as_ref()` | 转换为 Option<&T> | `opt.as_ref()` | | |
| `as_mut()` | 转换为 Option<&mut T> | `opt.as_mut()` | | |
| `copied()` | Option<&T> → Option<T>T: Copy | `opt.copied()` | | |
| `cloned()` | Option<&T> → Option<T>T: Clone | `opt.cloned()` | | |
---
# 🔚 七、一个综合示例
```rust
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert("Alice", 90);
scores.insert("Bob", 85);
let name = "Charlie";
let score = scores.get(name)
.copied() // Option<i32>
.unwrap_or_else(|| {
println!("{name} 不存在,使用默认分数");
60
});
println!("{name} 的分数是 {score}");
}
```
输出:
```
Charlie 不存在,使用默认分数
Charlie 的分数是 60
```
---
是否希望我接着帮你画一张「`Option<T>` 方法调用关系图(功能导图)」?
那张图能直观看出各种方法如何互相转换,非常适合记忆和快速查阅。