知识点1:Option --- 处理"可能有值,也可能没有"的情况
Rust 没有 null,而是用 Option 枚举来表示"有值"或"没值":
rust
fn main() {
// Option 有两个变体:
// Some(值) --- 有值
// None --- 没有值
let score: Option<i32> = Some(95);
let empty: Option<i32> = None;
// 用 match 处理 Option
match score {
Some(s) => println!("分数是: {}", s),
None => println!("没有分数"),
}
// 用 if let 简化(只关心有值的情况)
if let Some(s) = score {
println!("分数是: {}", s);
}
// 用 unwrap_or 提供默认值
println!("分数: {}", score.unwrap_or(0)); // 95
println!("分数: {}", empty.unwrap_or(0)); // 0
// 用 is_some / is_none 判断
println!("有值? {}", score.is_some()); // true
println!("为空? {}", empty.is_none()); // true
// 实际场景:Vec 的 pop 返回 Option
let mut v = vec![1, 2, 3];
match v.pop() {
Some(val) => println!("弹出了: {}", val),
None => println!("数组为空"),
}
}
知识点2:Result --- 处理"可能出错"的操作
rust
fn main() {
// Result 有两个变体:
// Ok(值) --- 成功
// Err(错误) --- 失败
// 模拟一个可能失败的除法
match divide(10, 2) {
Ok(result) => println!("结果: {}", result),
Err(e) => println!("错误: {}", e),
}
match divide(10, 0) {
Ok(result) => println!("结果: {}", result),
Err(e) => println!("错误: {}", e),
}
// 用 if let 只关心成功的情况
if let Ok(result) = divide(10, 3) {
println!("成功: {}", result);
}
}
fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err(String::from("除数不能为0"))
} else {
Ok(a / b)
}
}
核心规则
类型 变体 用途
Option Some(T) / None 值可能存在或不存在
Result<T, E> Ok(T) / Err(E) 操作可能成功或失败
处理方式 写法
match match x { Some(v) => ..., None => ... }
if let if let Some(v) = x { ... }
unwrap_or x.unwrap_or(默认值)
动手试试
补全下面的代码:
rust
fn main() {
// 补全:定义一个 find_item 函数,接收一个 Vec<i32> 和一个目标值 target
// 如果找到目标值,返回 Some(索引)
// 如果没找到,返回 None
// 提示:用 for 循环遍历,记录索引
let numbers = vec![10, 20, 30, 40, 50];
// 补全:调用 find_item 查找 30,用 match 打印结果
// 期望输出: 找到30,索引为: 2
// 补全:调用 find_item 查找 99,用 match 打印结果
// 期望输出: 没找到99
// 补全:定义一个 safe_sqrt 函数,接收 f64 参数
// 如果参数 >= 0,返回 Ok(平方根)
// 如果参数 < 0,返回 Err(String::from("负数没有平方根"))
// 提示:平方根用 x.sqrt()
// 补全:调用 safe_sqrt(16.0),用 match 打印结果
// 期望输出: 16的平方根: 4
// 补全:调用 safe_sqrt(-4.0),用 match 打印结果
// 期望输出: 错误: 负数没有平方根
}
期望输出:
找到30,索引为: 2
没找到99
16的平方根: 4
错误: 负数没有平方根
写好了贴过来,没问题就进入第11课:HashMap 键值对集合 👋
贴代码
rust
fn main() {
// 补全:定义一个 find_item 函数,接收一个 Vec<i32> 和一个目标值 target
// 如果找到目标值,返回 Some(索引)
// 如果没找到,返回 None
// 提示:用 for 循环遍历,记录索引
let numbers = vec![10, 20, 30, 40, 50];
// 补全:调用 find_item 查找 30,用 match 打印结果
// 期望输出: 找到30,索引为: 2
// 补全:调用 find_item 查找 99,用 match 打印结果
// 期望输出: 没找到99
// 补全:定义一个 safe_sqrt 函数,接收 f64 参数
// 如果参数 >= 0,返回 Ok(平方根)
// 如果参数 < 0,返回 Err(String::from("负数没有平方根"))
// 提示:平方根用 x.sqrt()
// 补全:调用 safe_sqrt(16.0),用 match 打印结果
// 期望输出: 16的平方根: 4
// 补全:调用 safe_sqrt(-4.0),用 match 打印结果
// 期望输出: 错误: 负数没有平方根
}
fn find_item(v: Vec<i32>, target: i32) -> Option<usize> {
for (index, &val) in v.iter().enumerate() {
if val == target {
return Some(index);
}
}
None
}
fn safe_sqrt(x: f64) -> Result<f64, String> {
if x >= 0.0 {
Ok(x.sqrt())
} else {
Err(String::from("负数没有平方根"))
}
}
接下来把 main 里面调用和 match 补完整:
rust
fn main() {
let numbers = vec![10, 20, 30, 40, 50];
// 查找30
match find_item(numbers.clone(), 30) {
Some(idx) => println!("找到30,索引为: {}", idx),
None => println!("没找到30"),
}
// 查找99
match find_item(numbers, 99) {
Some(idx) => println!("找到99,索引为: {}", idx),
None => println!("没找到99"),
}
// 平方根 16.0
match safe_sqrt(16.0) {
Ok(n) => println!("16的平方根: {}", n),
Err(e) => println!("错误: {}", e),
}
// 平方根 -4.0
match safe_sqrt(-4.0) {
Ok(n) => println!("-4的平方根: {}", n),
Err(e) => println!("错误: {}", e),
}
}
fn find_item(v: Vec<i32>, target: i32) -> Option<usize> {
for (index, &val) in v.iter().enumerate() {
if val == target {
return Some(index);
}
}
None
}
fn safe_sqrt(x: f64) -> Result<f64, String> {
if x >= 0.0 {
Ok(x.sqrt())
} else {
Err(String::from("负数没有平方根"))
}
}
运行输出:
plaintext
找到30,索引为: 2
没找到99
16的平方根: 4
错误: 负数没有平方根
核心知识点
- Option:代表可能有值、可能为空。 Some(值) / None 。常用于查找类函数。
- Result<T,E>:代表成功或者失败。 Ok(成功结果) / Err(错误信息) ,用于错误处理。
- .iter().enumerate() :同时拿到索引+元素,非常适合搜索位置。
- match:Rust 的模式匹配,专门用来拆开 Option / Result,两个分支必须写完整,不能漏。
- numbers.clone() :因为 find_item 获取 Vec 的所有权,第一次调用之后 numbers 就被移走了,第二次调用前需要克隆一份。
进阶提示:更好的写法是函数接收切片 &i32 , fn find_item(v: &i32, target:i32) ,就不需要 clone。初学阶段先用上面版本即可。
做完这道,Option、Result、match 基础就掌握了!