rust学习-Option与Result
- [1. Option 类型](#1. Option 类型)
-
- [1.1 什么是 Option?](#1.1 什么是 Option?)
- [1.2 创建 Option](#1.2 创建 Option)
- [1.3 处理 Option 的基本方法](#1.3 处理 Option 的基本方法)
-
- [使用 match 处理](#使用 match 处理)
- [使用 if let 处理](#使用 if let 处理)
- [1.4 Option 的常用方法](#1.4 Option 的常用方法)
-
- [unwrap 系列](#unwrap 系列)
- [map 和 and_then](#map 和 and_then)
- filter
- [or 和 or_else](#or 和 or_else)
- [get_or_insert 系列](#get_or_insert 系列)
- [1.5 Option 的转换方法](#1.5 Option 的转换方法)
- [2. Result 类型](#2. Result 类型)
-
- [2.1 什么是 Result?](#2.1 什么是 Result?)
- [2.2 创建 Result](#2.2 创建 Result)
- [2.3 自定义错误类型](#2.3 自定义错误类型)
- [2.4 Result 的常用方法](#2.4 Result 的常用方法)
-
- [unwrap 系列](#unwrap 系列)
- [map 系列](#map 系列)
- [and_then 和 or_else](#and_then 和 or_else)
- [错误传播:? 运算符](#错误传播:? 运算符)
- [2.5 组合多个 Result](#2.5 组合多个 Result)
- [3. 组合处理 Option 和 Result](#3. 组合处理 Option 和 Result)
-
- [3.1 Option 和 Result 的相互转换](#3.1 Option 和 Result 的相互转换)
- [3.2 transpose 方法](#3.2 transpose 方法)
- [3.3 处理嵌套类型](#3.3 处理嵌套类型)
- [4. 高级用法与模式](#4. 高级用法与模式)
-
- [4.1 自定义错误类型和 thiserror 库](#4.1 自定义错误类型和 thiserror 库)
- [4.2 anyhow 库用于应用程序错误处理](#4.2 anyhow 库用于应用程序错误处理)
- [4.3 模式匹配的高级用法](#4.3 模式匹配的高级用法)
- [5. 实际应用示例](#5. 实际应用示例)
-
- [5.1 配置文件解析](#5.1 配置文件解析)
- [5.2 数据库查询模拟](#5.2 数据库查询模拟)
- [6. 最佳实践](#6. 最佳实践)
-
- [6.1 何时使用 Option vs Result](#6.1 何时使用 Option vs Result)
- [6.2 错误处理策略](#6.2 错误处理策略)
- [6.3 性能考虑](#6.3 性能考虑)
Option 和 Result 是 Rust 中处理可能缺失的值和可能失败的操作的两个核心枚举类型。这是 Rust的安全哲学的一种体现:编译时强制错误处理。
1. Option :表示值可能存在 (Some(T)) 或不存在 (None)
2. Result<T, E>:表示操作可能成功 (Ok(T)) 或失败 (Err(E))
1. Option 类型
1.1 什么是 Option?
Option 是一个枚举,表示一个值可能存在 (Some) 或不存在 (None)。
rust
enum Option<T> {
Some(T), // 包含一个值 T
None, // 不包含任何值
}
1.2 创建 Option
rust
fn main() {
// 创建 Some 值
let some_number = Some(5);
let some_string = Some("hello");
// 创建 None 值 - 必须指定类型
let absent_number: Option<i32> = None;
// 使用 Option::Some 和 Option::None
let x = Option::Some(10);
let y: Option<String> = Option::None;
println!("{:?}, {:?}, {:?}, {:?}, {:?}",
some_number, some_string, absent_number, x, y);
}
1.3 处理 Option 的基本方法
使用 match 处理
rust
fn divide(numerator: f64, denominator: f64) -> Option<f64> {
if denominator == 0.0 {
None
} else {
Some(numerator / denominator)
}
}
fn main() {
let result = divide(10.0, 2.0);
match result {
Some(value) => println!("结果是: {}", value),
None => println!("不能除以零"),
}
let invalid = divide(10.0, 0.0);
match invalid {
Some(value) => println!("结果是: {}", value),
None => println!("不能除以零"),
}
}
使用 if let 处理
rust
fn main() {
let some_value = Some(42);
if let Some(x) = some_value {
println!("值是: {}", x);
} else {
println!("没有值");
}
// 只关心 Some 的情况
if let Some(x) = Some(100) {
println!("有值: {}", x);
}
}
1.4 Option 的常用方法
unwrap 系列
rust
fn main() {
let x = Some("value");
let y: Option<&str> = None;
// unwrap: 如果是 Some 返回值,如果是 None 则 panic
println!("x.unwrap() = {}", x.unwrap()); // "value"
// println!("y.unwrap() = {}", y.unwrap()); // 会 panic!
// unwrap_or: 提供默认值
println!("x.unwrap_or(\"default\") = {}", x.unwrap_or("default")); // "value"
println!("y.unwrap_or(\"default\") = {}", y.unwrap_or("default")); // "default"
// unwrap_or_else: 使用闭包计算默认值
println!("y.unwrap_or_else(|| \"computed\") = {}",
y.unwrap_or_else(|| "computed")); // "computed"
// expect: 类似 unwrap,但可以指定错误信息
println!("x.expect(\"出错了\") = {}", x.expect("出错了")); // "value"
// y.expect("值不存在"); // panic 并显示 "值不存在"
}
map 和 and_then
rust
fn main() {
let some_number = Some(10);
// map: 对 Some 中的值进行转换
let doubled = some_number.map(|x| x * 2);
println!("doubled = {:?}", doubled); // Some(20)
let none_number: Option<i32> = None;
let still_none = none_number.map(|x| x * 2);
println!("still_none = {:?}", still_none); // None
// and_then: 链式操作,返回 Option
fn square(x: i32) -> Option<i32> { Some(x * x) }
fn none_if_negative(x: i32) -> Option<i32> {
if x >= 0 { Some(x) } else { None }
}
let result = Some(4).and_then(square).and_then(|x| Some(x + 1));
println!("result = {:?}", result); // Some(17)
let chain_result = Some(-5).and_then(none_if_negative).and_then(square);
println!("chain_result = {:?}", chain_result); // None
}
filter
rust
fn main() {
let some_number = Some(10);
// filter: 根据条件过滤
let filtered = some_number.filter(|&x| x > 5);
println!("filtered = {:?}", filtered); // Some(10)
let filtered_none = some_number.filter(|&x| x > 20);
println!("filtered_none = {:?}", filtered_none); // None
// 使用 None
let none: Option<i32> = None;
println!("none.filter(...) = {:?}", none.filter(|&x| x > 5)); // None
}
or 和 or_else
rust
fn main() {
let x = Some(2);
let y = None;
let z = Some(100);
// or: 如果当前是 Some 则返回当前,否则返回另一个
println!("x.or(z) = {:?}", x.or(z)); // Some(2)
println!("y.or(z) = {:?}", y.or(z)); // Some(100)
println!("y.or(y) = {:?}", y.or(y)); // None
// or_else: 使用闭包
println!("y.or_else(|| Some(999)) = {:?}",
y.or_else(|| Some(999))); // Some(999)
}
get_or_insert 系列
rust
fn main() {
let mut x = None;
// get_or_insert: 如果是 None 则插入值
let value = x.get_or_insert(5);
println!("value = {}, x = {:?}", value, x); // 5, Some(5)
*value += 1;
println!("修改后 x = {:?}", x); // Some(6)
// get_or_insert_with: 使用闭包
let mut y: Option<String> = None;
let s = y.get_or_insert_with(|| "default".to_string());
println!("s = {}, y = {:?}", s, y); // "default", Some("default")
}
1.5 Option 的转换方法
rust
fn main() {
let some_option = Some(42);
let none_option: Option<i32> = None;
// ok_or: 将 Option 转换为 Result
let result_ok = some_option.ok_or("没有值");
println!("ok = {:?}", result_ok); // Ok(42)
let result_err = none_option.ok_or("没有值");
println!("err = {:?}", result_err); // Err("没有值")
// ok_or_else: 使用闭包创建错误
let result = none_option.ok_or_else(|| {
println!("计算错误信息");
"值不存在"
});
println!("result = {:?}", result); // Err("值不存在")
// 转换为迭代器
let iter = some_option.iter();
for value in iter {
println!("迭代器中的值: {}", value); // 42
}
// 检查是否包含特定值
println!("some_option.contains(&42) = {}", some_option.contains(&42)); // true
println!("some_option.contains(&100) = {}", some_option.contains(&100)); // false
}
2. Result 类型
2.1 什么是 Result?
Result<T, E> 是一个枚举,表示操作可能成功 (Ok) 或失败 (Err)。
rust
enum Result<T, E> {
Ok(T), // 包含成功值 T
Err(E), // 包含错误值 E
}
2.2 创建 Result
rust
use std::fs::File;
use std::io::Error;
fn main() {
// 创建 Ok 和 Err
let success: Result<i32, String> = Ok(42);
let failure: Result<i32, String> = Err(String::from("出错了"));
// 实际使用示例
let file_result = File::open("test.txt");
match file_result {
Ok(file) => println!("文件打开成功: {:?}", file),
Err(error) => println!("文件打开失败: {}", error),
}
}
2.3 自定义错误类型
rust
// 定义自己的错误类型
#[derive(Debug)]
enum MathError {
DivisionByZero,
NegativeSquareRoot,
Overflow,
}
impl std::fmt::Display for MathError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
MathError::DivisionByZero => write!(f, "除数不能为零"),
MathError::NegativeSquareRoot => write!(f, "不能对负数开平方根"),
MathError::Overflow => write!(f, "计算溢出"),
}
}
}
impl std::error::Error for MathError {}
fn divide(a: f64, b: f64) -> Result<f64, MathError> {
if b == 0.0 {
Err(MathError::DivisionByZero)
} else {
Ok(a / b)
}
}
fn main() {
match divide(10.0, 0.0) {
Ok(result) => println!("结果: {}", result),
Err(error) => println!("错误: {}", error),
}
}
2.4 Result 的常用方法
unwrap 系列
rust
fn main() {
let ok_result: Result<i32, &str> = Ok(42);
let err_result: Result<i32, &str> = Err("出错了");
// unwrap: 成功返回值,失败 panic
println!("ok_result.unwrap() = {}", ok_result.unwrap()); // 42
// println!("err_result.unwrap()"); // panic!
// unwrap_or: 提供默认值
println!("ok_result.unwrap_or(0) = {}", ok_result.unwrap_or(0)); // 42
println!("err_result.unwrap_or(0) = {}", err_result.unwrap_or(0)); // 0
// unwrap_or_else: 使用闭包计算默认值
println!("err_result.unwrap_or_else(|e| {
println!(\"错误是: {}\", e);
999
}) = {}", err_result.unwrap_or_else(|e| {
println!("错误是: {}", e);
999
})); // 打印错误,返回 999
// expect: 类似 unwrap,但可以指定错误信息
println!("ok_result.expect(\"不应该出错\") = {}",
ok_result.expect("不应该出错")); // 42
// err_result.expect("这里出错了"); // panic 并显示 "这里出错了: 出错了"
}
map 系列
rust
fn main() {
let ok: Result<i32, &str> = Ok(10);
let err: Result<i32, &str> = Err("错误");
// map: 转换成功值
let doubled = ok.map(|x| x * 2);
println!("doubled = {:?}", doubled); // Ok(20)
let still_err = err.map(|x| x * 2);
println!("still_err = {:?}", still_err); // Err("错误")
// map_err: 转换错误值
let mapped_err = err.map_err(|e| format!("严重错误: {}", e));
println!("mapped_err = {:?}", mapped_err); // Err("严重错误: 错误")
// map_or: 提供默认值并转换
println!("ok.map_or(0, |x| x * 2) = {}", ok.map_or(0, |x| x * 2)); // 20
println!("err.map_or(0, |x| x * 2) = {}", err.map_or(0, |x| x * 2)); // 0
// map_or_else: 使用闭包
let result = err.map_or_else(
|e| format!("错误: {}", e).len(), // 错误处理闭包
|x| x * 2 // 成功处理闭包
);
println!("map_or_else 结果 = {}", result); // 7 (中文字符长度)
}
and_then 和 or_else
rust
fn main() {
fn sqrt(x: f64) -> Result<f64, String> {
if x >= 0.0 {
Ok(x.sqrt())
} else {
Err(format!("不能计算 {} 的平方根", x))
}
}
fn reciprocal(x: f64) -> Result<f64, String> {
if x != 0.0 {
Ok(1.0 / x)
} else {
Err("不能计算倒数".to_string())
}
}
// and_then: 链式操作,每个步骤都可能失败
let result = Ok(16.0)
.and_then(sqrt) // Ok(4.0)
.and_then(reciprocal); // Ok(0.25)
println!("result = {:?}", result); // Ok(0.25)
let chain_err = Ok(-4.0).and_then(sqrt);
println!("chain_err = {:?}", chain_err); // Err("不能计算 -4 的平方根")
// or_else: 处理错误
let recovered = Err("原始错误".to_string())
.or_else(|_| Ok(42)); // 从错误中恢复
println!("recovered = {:?}", recovered); // Ok(42)
}
错误传播:? 运算符
rust
use std::fs::File;
use std::io::{self, Read};
// 传统错误处理
fn read_file_contents(path: &str) -> Result<String, io::Error> {
let mut file = match File::open(path) {
Ok(f) => f,
Err(e) => return Err(e),
};
let mut contents = String::new();
match file.read_to_string(&mut contents) {
Ok(_) => Ok(contents),
Err(e) => Err(e),
}
}
// 使用 ? 运算符简化
fn read_file_contents_simple(path: &str) -> Result<String, io::Error> {
let mut file = File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
// 更简洁的写法
fn read_file_contents_even_simpler(path: &str) -> Result<String, io::Error> {
let mut contents = String::new();
File::open(path)?.read_to_string(&mut contents)?;
Ok(contents)
}
fn main() {
match read_file_contents_simple("test.txt") {
Ok(contents) => println!("文件内容: {}", contents),
Err(e) => println!("读取失败: {}", e),
}
}
2.5 组合多个 Result
rust
use std::error::Error;
use std::fmt;
#[derive(Debug)]
struct AppError {
details: String,
}
impl fmt::Display for AppError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "应用错误: {}", self.details)
}
}
impl Error for AppError {}
impl From<std::io::Error> for AppError {
fn from(err: std::io::Error) -> Self {
AppError {
details: format!("IO错误: {}", err),
}
}
}
impl From<std::num::ParseIntError> for AppError {
fn from(err: std::num::ParseIntError) -> Self {
AppError {
details: format!("解析错误: {}", err),
}
}
}
fn parse_number(s: &str) -> Result<i32, AppError> {
Ok(s.parse()?)
}
fn read_and_parse() -> Result<i32, AppError> {
// 模拟读取文件
let content = std::fs::read_to_string("number.txt")?;
let number = parse_number(&content)?;
Ok(number)
}
fn main() {
match read_and_parse() {
Ok(n) => println!("解析到的数字: {}", n),
Err(e) => println!("错误: {}", e),
}
}
3. 组合处理 Option 和 Result
3.1 Option 和 Result 的相互转换
rust
fn main() {
// Option -> Result
let some_value = Some(42);
let none_value: Option<i32> = None;
let result_ok = some_value.ok_or("没有值");
println!("some -> result: {:?}", result_ok); // Ok(42)
let result_err = none_value.ok_or("没有值");
println!("none -> result: {:?}", result_err); // Err("没有值")
// Result -> Option
let ok_result: Result<i32, &str> = Ok(42);
let err_result: Result<i32, &str> = Err("错误");
println!("ok -> option: {:?}", ok_result.ok()); // Some(42)
println!("err -> option: {:?}", err_result.ok()); // None
println!("ok -> err option: {:?}", ok_result.err()); // None
println!("err -> err option: {:?}", err_result.err()); // Some("错误")
}
3.2 transpose 方法
rust
fn main() {
// Option<Result<T, E>> -> Result<Option<T>, E>
let option_result: Option<Result<i32, &str>> = Some(Ok(42));
let result_option: Result<Option<i32>, &str> = option_result.transpose();
println!("transpose 1: {:?}", result_option); // Ok(Some(42))
let option_err: Option<Result<i32, &str>> = Some(Err("错误"));
println!("transpose 2: {:?}", option_err.transpose()); // Err("错误")
let none_option: Option<Result<i32, &str>> = None;
println!("transpose 3: {:?}", none_option.transpose()); // Ok(None)
}
3.3 处理嵌套类型
rust
fn process_nested(value: Option<Result<i32, String>>) -> Result<Option<String>, String> {
value
.transpose()? // Option<Result> -> Result<Option>
.map(|num| num.to_string()) // Option<i32> -> Option<String>
.transpose() // Result<Option<String>> 保持原样
}
fn main() {
let nested1 = Some(Ok(42));
let nested2 = Some(Err(String::from("错误")));
let nested3: Option<Result<i32, String>> = None;
println!("{:?}", process_nested(nested1)); // Ok(Some("42"))
println!("{:?}", process_nested(nested2)); // Err("错误")
println!("{:?}", process_nested(nested3)); // Ok(None)
}
4. 高级用法与模式
4.1 自定义错误类型和 thiserror 库
rust
// 使用 thiserror 库简化错误定义
// Cargo.toml: thiserror = "1.0"
use thiserror::Error;
#[derive(Error, Debug)]
enum MyError {
#[error("IO错误: {0}")]
Io(#[from] std::io::Error),
#[error("解析错误: {0}")]
Parse(#[from] std::num::ParseIntError),
#[error("自定义错误: {0}")]
Custom(String),
#[error("数值 {0} 超出范围")]
OutOfRange(i32),
}
fn process_data(path: &str) -> Result<i32, MyError> {
let content = std::fs::read_to_string(path)?; // 自动转换为 MyError::Io
let num: i32 = content.trim().parse()?; // 自动转换为 MyError::Parse
if num < 0 || num > 100 {
return Err(MyError::OutOfRange(num));
}
if num == 42 {
return Err(MyError::Custom("不能是 42".to_string()));
}
Ok(num * 2)
}
fn main() {
match process_data("data.txt") {
Ok(result) => println!("结果: {}", result),
Err(e) => println!("错误: {}", e),
}
}
4.2 anyhow 库用于应用程序错误处理
rust
// 使用 anyhow 库简化错误处理
// Cargo.toml: anyhow = "1.0"
use anyhow::{Context, Result};
fn read_config() -> Result<String> {
let path = "config.toml";
let content = std::fs::read_to_string(path)
.with_context(|| format!("无法读取配置文件: {}", path))?;
Ok(content)
}
fn parse_port(content: &str) -> Result<u16> {
// 简单解析示例
let port: u16 = content.trim().parse()
.context("端口号解析失败")?;
if port < 1024 {
anyhow::bail!("端口号 {} 需要特权", port);
}
Ok(port)
}
fn main() -> Result<()> {
let config = read_config()?;
let port = parse_port(&config)?;
println!("使用端口: {}", port);
Ok(())
}
4.3 模式匹配的高级用法
rust
fn process_result(result: Result<i32, String>) {
match result {
Ok(0) => println!("结果是零"),
Ok(n @ 1..=10) => println!("结果在1-10之间: {}", n), // 绑定模式
Ok(n) if n % 2 == 0 => println!("结果是偶数: {}", n), // 守卫条件
Ok(n) => println!("结果是正数: {}", n),
Err(ref e) if e.contains("超时") => println!("超时错误"),
Err(e) => println!("其他错误: {}", e),
}
}
fn extract_inner(result: Result<Option<i32>, String>) {
if let Ok(Some(value @ 1..=100)) = result {
println!("有效值: {}", value);
}
}
fn main() {
process_result(Ok(5)); // 结果在1-10之间: 5
process_result(Ok(12)); // 结果是偶数: 12
process_result(Err("连接超时".to_string())); // 超时错误
extract_inner(Ok(Some(42))); // 有效值: 42
}
5. 实际应用示例
5.1 配置文件解析
rust
use std::collections::HashMap;
use std::fs;
type Config = HashMap<String, String>;
fn parse_config(path: &str) -> Option<Config> {
let content = fs::read_to_string(path).ok()?;
let mut config = HashMap::new();
for line in content.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
let parts: Vec<&str> = line.splitn(2, '=').collect();
if parts.len() == 2 {
config.insert(
parts[0].trim().to_string(),
parts[1].trim().to_string(),
);
}
}
Some(config)
}
fn get_config_value(config: &Config, key: &str) -> Result<&str, String> {
config
.get(key)
.map(|s| s.as_str())
.ok_or_else(|| format!("配置项 '{}' 不存在", key))
}
fn main() {
let config = parse_config("config.cfg").unwrap_or_default();
match get_config_value(&config, "port") {
Ok(port_str) => {
match port_str.parse::<u16>() {
Ok(port) if port > 0 => println!("端口号: {}", port),
Ok(_) => eprintln!("端口号必须大于0"),
Err(_) => eprintln!("端口号格式错误"),
}
}
Err(e) => eprintln!("{}", e),
}
}
5.2 数据库查询模拟
rust
use std::error::Error;
use std::fmt;
#[derive(Debug, Clone)]
struct User {
id: u32,
name: String,
email: Option<String>,
}
#[derive(Debug)]
enum DatabaseError {
ConnectionFailed,
UserNotFound(u32),
InvalidQuery,
}
impl fmt::Display for DatabaseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DatabaseError::ConnectionFailed => write!(f, "数据库连接失败"),
DatabaseError::UserNotFound(id) => write!(f, "用户 {} 不存在", id),
DatabaseError::InvalidQuery => write!(f, "查询语句无效"),
}
}
}
impl Error for DatabaseError {}
struct Database {
connected: bool,
users: Vec<User>,
}
impl Database {
fn new() -> Self {
Database {
connected: false,
users: vec![
User { id: 1, name: "Alice".to_string(), email: Some("alice@example.com".to_string()) },
User { id: 2, name: "Bob".to_string(), email: None },
User { id: 3, name: "Charlie".to_string(), email: Some("charlie@example.com".to_string()) },
],
}
}
fn connect(&mut self) -> Result<(), DatabaseError> {
// 模拟连接有时成功有时失败
self.connected = true;
Ok(())
}
fn find_user_by_id(&self, id: u32) -> Result<Option<User>, DatabaseError> {
if !self.connected {
return Err(DatabaseError::ConnectionFailed);
}
let user = self.users.iter().find(|u| u.id == id).cloned();
Ok(user)
}
fn get_user_email(&self, id: u32) -> Result<Option<String>, DatabaseError> {
self.find_user_by_id(id)?
.and_then(|user| user.email)
.pipe(Ok) // 包装回 Result
}
}
// 辅助扩展方法
trait Pipe {
fn pipe<F, T>(self, f: F) -> T
where
F: FnOnce(Self) -> T,
Self: Sized;
}
impl<T> Pipe for T {
fn pipe<F, R>(self, f: F) -> R
where
F: FnOnce(Self) -> R,
{
f(self)
}
}
fn main() -> Result<(), Box<dyn Error>> {
let mut db = Database::new();
// 连接数据库
db.connect()?;
// 查询用户
match db.find_user_by_id(2)? {
Some(user) => {
println!("找到用户: {}", user.name);
if let Some(email) = user.email {
println!("邮箱: {}", email);
} else {
println!("该用户没有邮箱");
}
}
None => println!("用户不存在"),
}
// 直接获取邮箱
match db.get_user_email(1)? {
Some(email) => println!("邮箱: {}", email),
None => println!("没有邮箱"),
}
// 处理不存在的用户
match db.get_user_email(999) {
Ok(None) => println!("用户 999 没有邮箱"),
Ok(Some(email)) => println!("邮箱: {}", email),
Err(e) => println!("查询失败: {}", e),
}
Ok(())
}
6. 最佳实践
6.1 何时使用 Option vs Result
-
使用 Option:
- 当值可能不存在是正常情况时
- 查找操作(如 HashMap::get)
- 可选配置项
-
使用 Result:
- 当操作可能失败且需要错误信息时
- I/O 操作
- 网络请求
- 解析操作
6.2 错误处理策略
1. 传播错误 :使用 ? 运算符向上传播错误
2. 转换错误 :使用 map_err 或 From trait 转换错误类型
3. 恢复错误 :使用 or_else 或 unwrap_or 提供默认值
4. 组合错误:使用 anyhow 或 thiserror 库管理复杂错误类型
6.3 性能考虑
rust
// 使用 Result 而不是 panic 进行错误处理
fn divide_result(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("除数不能为零".to_string())
} else {
Ok(a / b)
}
}
// 避免过度使用 unwrap,使用模式匹配
fn safe_access(vec: &[i32], index: usize) -> Option<i32> {
// 好:使用 get 返回 Option
vec.get(index).copied()
// 不好:可能 panic
// Some(vec[index])
}
// 对于性能关键代码,考虑使用 unwrap
fn performance_critical(vec: &[i32]) -> i32 {
// 只在确定不会失败时使用 unwrap
vec.first().copied().unwrap_or(0)
}