本章概述

错误处理是编程中的重要主题,Rust通过其类型系统提供了安全且表达力强的错误处理机制。与许多语言使用异常不同,Rust使用ResultOption类型来显式处理错误和空值情况。本章将深入探讨Rust的错误处理哲学和实践。

学习目标

  • 🎯 理解Rust错误处理的设计哲学
  • 🎯 掌握ResultOption类型的使用
  • 🎯 学会错误传播和处理策略
  • 🎯 了解如何创建自定义错误类型
  • 🎯 掌握错误处理的最佳实践
  • 🎯 学会使用?操作符简化错误处理

8.1 错误处理基础

8.1.1 Rust的错误处理哲学

fn main() {
    println!("🚨 Rust错误处理哲学");
    println!("==================");
    
    demonstrate_explicit_errors();
    demonstrate_recoverable_vs_unrecoverable();
    demonstrate_type_safety();
}

// 显式错误处理
fn demonstrate_explicit_errors() {
    println!("\n1. 显式错误处理:");
    println!("   - 错误是类型系统的一部分");
    println!("   - 必须显式处理或传播错误");
    println!("   - 编译器强制错误处理");
    
    // 示例:文件读取可能失败
    match std::fs::read_to_string("nonexistent.txt") {
        Ok(content) => println!("文件内容: {}", content),
        Err(error) => println!("读取文件失败: {}", error),
    }
    
    // 示例:字符串解析可能失败
    let number_str = "42";
    match number_str.parse::<i32>() {
        Ok(number) => println!("解析成功: {}", number),
        Err(error) => println!("解析失败: {}", error),
    }
}

// 可恢复 vs 不可恢复错误
fn demonstrate_recoverable_vs_unrecoverable() {
    println!("\n2. 错误类型分类:");
    println!("   - 可恢复错误: 使用Result<T, E>");
    println!("   - 不可恢复错误: 使用panic!");
    
    // 可恢复错误示例
    fn divide(a: f64, b: f64) -> Result<f64, String> {
        if b == 0.0 {
            Err("除零错误".to_string())
        } else {
            Ok(a / b)
        }
    }
    
    match divide(10.0, 2.0) {
        Ok(result) => println!("除法结果: {}", result),
        Err(error) => println!("除法错误: {}", error),
    }
    
    match divide(10.0, 0.0) {
        Ok(result) => println!("除法结果: {}", result),
        Err(error) => println!("除法错误: {}", error),
    }
    
    // 不可恢复错误示例(注释掉以避免程序崩溃)
    // panic!("这是一个不可恢复的错误!");
    
    println!("   注意: panic!会导致程序崩溃,只在无法恢复的情况下使用");
}

// 类型安全
fn demonstrate_type_safety() {
    println!("\n3. 类型安全:");
    println!("   - 错误类型在编译时确定");
    println!("   - 防止忘记处理错误");
    println!("   - 提供丰富的错误信息");
    
    // 类型安全的错误处理
    #[derive(Debug)]
    enum MathError {
        DivisionByZero,
        NegativeSquareRoot,
        Overflow,
    }
    
    fn safe_divide(a: i32, b: i32) -> Result<i32, MathError> {
        if b == 0 {
            Err(MathError::DivisionByZero)
        } else {
            match a.checked_div(b) {
                Some(result) => Ok(result),
                None => Err(MathError::Overflow),
            }
        }
    }
    
    fn safe_sqrt(x: f64) -> Result<f64, MathError> {
        if x < 0.0 {
            Err(MathError::NegativeSquareRoot)
        } else {
            Ok(x.sqrt())
        }
    }
    
    // 使用类型安全的错误处理
    match safe_divide(10, 2) {
        Ok(result) => println!("安全除法: 10 / 2 = {}", result),
        Err(error) => println!("除法错误: {:?}", error),
    }
    
    match safe_sqrt(-4.0) {
        Ok(result) => println!("平方根: {}", result),
        Err(error) => println!("平方根错误: {:?}", error),
    }
}
rustc error_philosophy.rs && ./error_philosophy

8.1.2 Option类型详解

fn main() {
    println!("🔍 Option类型深入");
    println!("================");
    
    demonstrate_option_basics();
    demonstrate_option_methods();
    demonstrate_option_patterns();
    demonstrate_option_chaining();
}

fn demonstrate_option_basics() {
    println!("\nOption基础:");
    
    // Option表示可能存在或不存在的值
    let some_number = Some(42);
    let no_number: Option<i32> = None;
    
    println!("some_number: {:?}", some_number);
    println!("no_number: {:?}", no_number);
    
    // 使用match处理Option
    match some_number {
        Some(value) => println!("找到值: {}", value),
        None => println!("没有值"),
    }
    
    match no_number {
        Some(value) => println!("找到值: {}", value),
        None => println!("没有值"),
    }
    
    // 实际应用:查找数组中的元素
    let numbers = vec![1, 2, 3, 4, 5];
    
    fn find_even(numbers: &[i32]) -> Option<i32> {
        for &num in numbers {
            if num % 2 == 0 {
                return Some(num);
            }
        }
        None
    }
    
    match find_even(&numbers) {
        Some(even) => println!("找到第一个偶数: {}", even),
        None => println!("没有找到偶数"),
    }
}

fn demonstrate_option_methods() {
    println!("\nOption常用方法:");
    
    let some_value = Some("hello");
    let no_value: Option<&str> = None;
    
    // is_some() 和 is_none()
    println!("some_value.is_some(): {}", some_value.is_some());
    println!("some_value.is_none(): {}", some_value.is_none());
    println!("no_value.is_some(): {}", no_value.is_some());
    println!("no_value.is_none(): {}", no_value.is_none());
    
    // unwrap() - 获取值,如果是None则panic
    println!("some_value.unwrap(): {}", some_value.unwrap());
    // no_value.unwrap(); // 这会panic!
    
    // unwrap_or() - 提供默认值
    println!("some_value.unwrap_or(\"default\"): {}", some_value.unwrap_or("default"));
    println!("no_value.unwrap_or(\"default\"): {}", no_value.unwrap_or("default"));
    
    // unwrap_or_else() - 使用闭包计算默认值
    println!("no_value.unwrap_or_else(): {}", 
             no_value.unwrap_or_else(|| "computed default"));
    
    // expect() - 带自定义错误消息的unwrap
    println!("some_value.expect(): {}", some_value.expect("应该有值"));
    
    // map() - 转换Option中的值
    let number = Some(42);
    let doubled = number.map(|x| x * 2);
    println!("number.map(|x| x * 2): {:?}", doubled);
    
    let no_number: Option<i32> = None;
    let doubled_none = no_number.map(|x| x * 2);
    println!("no_number.map(|x| x * 2): {:?}", doubled_none);
    
    // and_then() - 链式操作
    let result = Some("42")
        .and_then(|s| s.parse::<i32>().ok())
        .and_then(|n| if n > 0 { Some(n * 2) } else { None });
    println!("链式操作结果: {:?}", result);
    
    // filter() - 过滤值
    let filtered = Some(42).filter(|&x| x > 40);
    println!("Some(42).filter(|&x| x > 40): {:?}", filtered);
    
    let filtered_out = Some(30).filter(|&x| x > 40);
    println!("Some(30).filter(|&x| x > 40): {:?}", filtered_out);
}

fn demonstrate_option_patterns() {
    println!("\nOption模式匹配:");
    
    let values = vec![Some(1), None, Some(3), Some(4), None];
    
    // 基本模式匹配
    for (i, value) in values.iter().enumerate() {
        match value {
            Some(n) => println!("位置 {}: 值 = {}", i, n),
            None => println!("位置 {}: 无值", i),
        }
    }
    
    // if let 模式
    println!("\n使用 if let:");
    for (i, value) in values.iter().enumerate() {
        if let Some(n) = value {
            println!("位置 {}: 值 = {}", i, n);
        }
    }
    
    // while let 模式
    println!("\n使用 while let:");
    let mut iter = values.iter();
    while let Some(option_value) = iter.next() {
        if let Some(value) = option_value {
            println!("迭代到值: {}", value);
        } else {
            println!("迭代到None");
        }
    }
    
    // 嵌套Option
    let nested: Option<Option<i32>> = Some(Some(42));
    match nested {
        Some(Some(value)) => println!("嵌套值: {}", value),
        Some(None) => println!("外层Some,内层None"),
        None => println!("外层None"),
    }
    
    // flatten() 展平嵌套Option
    let flattened = nested.flatten();
    println!("展平后: {:?}", flattened);
}

fn demonstrate_option_chaining() {
    println!("\nOption链式操作:");
    
    #[derive(Debug)]
    struct Person {
        name: String,
        age: Option<u32>,
        address: Option<Address>,
    }
    
    #[derive(Debug)]
    struct Address {
        street: String,
        city: String,
        postal_code: Option<String>,
    }
    
    let person = Person {
        name: "张三".to_string(),
        age: Some(30),
        address: Some(Address {
            street: "中山路123号".to_string(),
            city: "北京".to_string(),
            postal_code: Some("100000".to_string()),
        }),
    };
    
    // 安全地访问嵌套的Option字段
    let postal_code = person.address
        .as_ref()
        .and_then(|addr| addr.postal_code.as_ref());
    
    match postal_code {
        Some(code) => println!("邮政编码: {}", code),
        None => println!("没有邮政编码"),
    }
    
    // 使用map进行转换
    let age_in_months = person.age.map(|age| age * 12);
    println!("年龄(月): {:?}", age_in_months);
    
    // 组合多个Option
    fn format_person_info(person: &Person) -> Option<String> {
        person.age.map(|age| {
            format!("{} ({} 岁)", person.name, age)
        })
    }
    
    if let Some(info) = format_person_info(&person) {
        println!("人员信息: {}", info);
    }
    
    // 使用zip组合两个Option
    let option1 = Some(10);
    let option2 = Some(20);
    let combined = option1.zip(option2).map(|(a, b)| a + b);
    println!("组合结果: {:?}", combined);
    
    // 收集Option向量
    let options = vec![Some(1), Some(2), None, Some(4)];
    let collected: Option<Vec<i32>> = options.into_iter().collect();
    println!("收集结果: {:?}", collected); // None,因为包含None
    
    let options2 = vec![Some(1), Some(2), Some(3), Some(4)];
    let collected2: Option<Vec<i32>> = options2.into_iter().collect();
    println!("收集结果2: {:?}", collected2); // Some([1, 2, 3, 4])
}
rustc option_deep_dive.rs && ./option_deep_dive

8.2 Result类型详解

8.2.1 Result基础和方法

fn main() {
    println!("📊 Result类型深入");
    println!("================");
    
    demonstrate_result_basics();
    demonstrate_result_methods();
    demonstrate_result_patterns();
    demonstrate_result_conversion();
}

fn demonstrate_result_basics() {
    println!("\nResult基础:");
    
    // Result表示可能成功或失败的操作
    let success: Result<i32, String> = Ok(42);
    let failure: Result<i32, String> = Err("出错了".to_string());
    
    println!("success: {:?}", success);
    println!("failure: {:?}", failure);
    
    // 使用match处理Result
    match success {
        Ok(value) => println!("成功: {}", value),
        Err(error) => println!("错误: {}", error),
    }
    
    match failure {
        Ok(value) => println!("成功: {}", value),
        Err(error) => println!("错误: {}", error),
    }
    
    // 实际应用:文件操作
    fn read_file_size(filename: &str) -> Result<u64, std::io::Error> {
        let metadata = std::fs::metadata(filename)?;
        Ok(metadata.len())
    }
    
    match read_file_size("Cargo.toml") {
        Ok(size) => println!("文件大小: {} 字节", size),
        Err(error) => println!("读取文件失败: {}", error),
    }
}

fn demonstrate_result_methods() {
    println!("\nResult常用方法:");
    
    let success: Result<i32, String> = Ok(42);
    let failure: Result<i32, String> = Err("错误".to_string());
    
    // is_ok() 和 is_err()
    println!("success.is_ok(): {}", success.is_ok());
    println!("success.is_err(): {}", success.is_err());
    println!("failure.is_ok(): {}", failure.is_ok());
    println!("failure.is_err(): {}", failure.is_err());
    
    // unwrap() - 获取Ok值,如果是Err则panic
    println!("success.unwrap(): {}", success.unwrap());
    // failure.unwrap(); // 这会panic!
    
    // unwrap_or() - 提供默认值
    println!("success.unwrap_or(0): {}", success.unwrap_or(0));
    println!("failure.unwrap_or(0): {}", failure.unwrap_or(0));
    
    // unwrap_or_else() - 使用闭包处理错误
    let result = failure.unwrap_or_else(|err| {
        println!("处理错误: {}", err);
        -1
    });
    println!("unwrap_or_else结果: {}", result);
    
    // expect() - 带自定义错误消息的unwrap
    println!("success.expect(): {}", success.expect("应该成功"));
    
    // map() - 转换Ok值
    let doubled = success.map(|x| x * 2);
    println!("success.map(|x| x * 2): {:?}", doubled);
    
    let doubled_err = failure.map(|x| x * 2);
    println!("failure.map(|x| x * 2): {:?}", doubled_err);
    
    // map_err() - 转换Err值
    let mapped_err = failure.map_err(|err| format!("映射错误: {}", err));
    println!("failure.map_err(): {:?}", mapped_err);
    
    // and_then() - 链式操作(成功时)
    let result = Ok("42")
        .and_then(|s| s.parse::<i32>().map_err(|e| e.to_string()))
        .and_then(|n| if n > 0 { Ok(n * 2) } else { Err("负数".to_string()) });
    println!("链式操作结果: {:?}", result);
    
    // or_else() - 链式操作(失败时)
    let recovery = Err("第一次失败")
        .or_else(|_| Ok("恢复成功"))
        .or_else(|_| Err("最终失败"));
    println!("错误恢复: {:?}", recovery);
}

fn demonstrate_result_patterns() {
    println!("\nResult模式匹配:");
    
    let results = vec![
        Ok(1),
        Err("错误1".to_string()),
        Ok(3),
        Err("错误2".to_string()),
    ];
    
    // 基本模式匹配
    for (i, result) in results.iter().enumerate() {
        match result {
            Ok(value) => println!("结果 {}: 成功 = {}", i, value),
            Err(error) => println!("结果 {}: 错误 = {}", i, error),
        }
    }
    
    // if let 模式
    println!("\n使用 if let:");
    for (i, result) in results.iter().enumerate() {
        if let Ok(value) = result {
            println!("结果 {}: 成功 = {}", i, value);
        }
    }
    
    // 嵌套Result处理
    fn parse_and_double(s: &str) -> Result<Result<i32, String>, std::num::ParseIntError> {
        let parsed = s.parse::<i32>()?;
        if parsed > 0 {
            Ok(Ok(parsed * 2))
        } else {
            Ok(Err("负数或零".to_string()))
        }
    }
    
    match parse_and_double("42") {
        Ok(Ok(value)) => println!("嵌套成功: {}", value),
        Ok(Err(error)) => println!("内层错误: {}", error),
        Err(error) => println!("外层错误: {}", error),
    }
    
    // flatten() 展平嵌套Result
    let nested: Result<Result<i32, String>, String> = Ok(Ok(42));
    let flattened = nested.flatten();
    println!("展平后: {:?}", flattened);
}

fn demonstrate_result_conversion() {
    println!("\nResult转换:");
    
    // Result和Option之间的转换
    let result: Result<i32, String> = Ok(42);
    let option = result.ok(); // Result -> Option
    println!("Result转Option: {:?}", option);
    
    let error_result: Result<i32, String> = Err("错误".to_string());
    let none_option = error_result.ok();
    println!("错误Result转Option: {:?}", none_option);
    
    let option: Option<i32> = Some(42);
    let result = option.ok_or("没有值".to_string()); // Option -> Result
    println!("Option转Result: {:?}", result);
    
    let none: Option<i32> = None;
    let error_result = none.ok_or("没有值".to_string());
    println!("None转Result: {:?}", error_result);
    
    // 使用ok_or_else()提供动态错误
    let dynamic_error = none.ok_or_else(|| {
        format!("动态错误消息: {}", "没有值")
    });
    println!("动态错误: {:?}", dynamic_error);
    
    // 收集Result向量
    let results = vec![Ok(1), Ok(2), Ok(3)];
    let collected: Result<Vec<i32>, String> = results.into_iter().collect();
    println!("收集成功结果: {:?}", collected);
    
    let mixed_results = vec![Ok(1), Err("错误".to_string()), Ok(3)];
    let collected_mixed: Result<Vec<i32>, String> = mixed_results.into_iter().collect();
    println!("收集混合结果: {:?}", collected_mixed); // 遇到第一个错误就停止
    
    // 分离成功和失败
    let results = vec![Ok(1), Err("错误1"), Ok(3), Err("错误2")];
    let (successes, errors): (Vec<_>, Vec<_>) = results.into_iter().partition(Result::is_ok);
    let success_values: Vec<i32> = successes.into_iter().map(Result::unwrap).collect();
    let error_values: Vec<String> = errors.into_iter().map(Result::unwrap_err).collect();
    
    println!("成功值: {:?}", success_values);
    println!("错误值: {:?}", error_values);
}
rustc result_deep_dive.rs && ./result_deep_dive

8.2.2 错误传播和?操作符

use std::fs::File;
use std::io::{self, Read};
use std::num::ParseIntError;

fn main() {
    println!("🔄 错误传播");
    println!("==========");
    
    demonstrate_manual_propagation();
    demonstrate_question_mark_operator();
    demonstrate_early_return();
    demonstrate_multiple_error_types();
}

fn demonstrate_manual_propagation() {
    println!("\n手动错误传播:");
    
    // 传统的错误传播方式
    fn read_file_manual(filename: &str) -> Result<String, io::Error> {
        let mut file = match File::open(filename) {
            Ok(file) => file,
            Err(error) => return Err(error),
        };
        
        let mut contents = String::new();
        match file.read_to_string(&mut contents) {
            Ok(_) => Ok(contents),
            Err(error) => Err(error),
        }
    }
    
    match read_file_manual("Cargo.toml") {
        Ok(contents) => println!("文件内容长度: {} 字符", contents.len()),
        Err(error) => println!("读取失败: {}", error),
    }
}

fn demonstrate_question_mark_operator() {
    println!("\n?操作符:");
    
    // 使用?操作符简化错误传播
    fn read_file_simple(filename: &str) -> Result<String, io::Error> {
        let mut file = File::open(filename)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        Ok(contents)
    }
    
    // 更简洁的版本
    fn read_file_concise(filename: &str) -> Result<String, io::Error> {
        std::fs::read_to_string(filename)
    }
    
    match read_file_simple("Cargo.toml") {
        Ok(contents) => println!("简化版文件内容长度: {} 字符", contents.len()),
        Err(error) => println!("读取失败: {}", error),
    }
    
    // ?操作符的工作原理
    fn demonstrate_question_mark_mechanics() -> Result<i32, ParseIntError> {
        // 这行代码:
        let number = "42".parse::<i32>()?;
        
        // 等价于:
        // let number = match "42".parse::<i32>() {
        //     Ok(n) => n,
        //     Err(e) => return Err(e),
        // };
        
        Ok(number * 2)
    }
    
    match demonstrate_question_mark_mechanics() {
        Ok(result) => println!("?操作符结果: {}", result),
        Err(error) => println!("解析错误: {}", error),
    }
}

fn demonstrate_early_return() {
    println!("\n提前返回模式:");
    
    fn process_data(input: &str) -> Result<i32, String> {
        // 验证输入不为空
        if input.is_empty() {
            return Err("输入不能为空".to_string());
        }
        
        // 解析数字
        let number = input.parse::<i32>()
            .map_err(|_| "无效的数字格式".to_string())?;
        
        // 验证数字范围
        if number < 0 {
            return Err("数字不能为负".to_string());
        }
        
        if number > 100 {
            return Err("数字不能大于100".to_string());
        }
        
        // 处理数据
        Ok(number * 2)
    }
    
    let test_cases = vec![
        "",
        "abc",
        "-5",
        "150",
        "42",
    ];
    
    for input in test_cases {
        match process_data(input) {
            Ok(result) => println!("输入 '{}' -> 结果: {}", input, result),
            Err(error) => println!("输入 '{}' -> 错误: {}", input, error),
        }
    }
}

fn demonstrate_multiple_error_types() {
    println!("\n多种错误类型:");
    
    // 定义自定义错误类型
    #[derive(Debug)]
    enum AppError {
        Io(io::Error),
        Parse(ParseIntError),
        Custom(String),
    }
    
    // 实现From trait进行错误转换
    impl From<io::Error> for AppError {
        fn from(error: io::Error) -> Self {
            AppError::Io(error)
        }
    }
    
    impl From<ParseIntError> for AppError {
        fn from(error: ParseIntError) -> Self {
            AppError::Parse(error)
        }
    }
    
    // 使用统一的错误类型
    fn read_and_parse_number(filename: &str) -> Result<i32, AppError> {
        let contents = std::fs::read_to_string(filename)?; // io::Error -> AppError
        let trimmed = contents.trim();
        
        if trimmed.is_empty() {
            return Err(AppError::Custom("文件为空".to_string()));
        }
        
        let number = trimmed.parse::<i32>()?; // ParseIntError -> AppError
        Ok(number)
    }
    
    // 创建测试文件
    std::fs::write("test_number.txt", "42").unwrap();
    
    match read_and_parse_number("test_number.txt") {
        Ok(number) => println!("解析的数字: {}", number),
        Err(AppError::Io(error)) => println!("IO错误: {}", error),
        Err(AppError::Parse(error)) => println!("解析错误: {}", error),
        Err(AppError::Custom(message)) => println!("自定义错误: {}", message),
    }
    
    // 清理测试文件
    let _ = std::fs::remove_file("test_number.txt");
    
    // 使用Box<dyn Error>处理多种错误类型
    fn flexible_error_handling(input: &str) -> Result<i32, Box<dyn std::error::Error>> {
        let number = input.parse::<i32>()?;
        
        if number < 0 {
            return Err("负数不被允许".into());
        }
        
        Ok(number * 2)
    }
    
    match flexible_error_handling("42") {
        Ok(result) => println!("灵活错误处理结果: {}", result),
        Err(error) => println!("灵活错误处理失败: {}", error),
    }
    
    match flexible_error_handling("-5") {
        Ok(result) => println!("灵活错误处理结果: {}", result),
        Err(error) => println!("灵活错误处理失败: {}", error),
    }
}
rustc error_propagation.rs && ./error_propagation

8.3 自定义错误类型

8.3.1 创建自定义错误

use std::fmt;
use std::error::Error;
use std::num::ParseIntError;
use std::io;

fn main() {
    println!("🎨 自定义错误类型");
    println!("================");
    
    demonstrate_simple_custom_error();
    demonstrate_enum_error();
    demonstrate_error_trait();
    demonstrate_error_chain();
}

// 简单的自定义错误
#[derive(Debug, Clone)]
struct SimpleError {
    message: String,
}

impl SimpleError {
    fn new(message: &str) -> Self {
        SimpleError {
            message: message.to_string(),
        }
    }
}

impl fmt::Display for SimpleError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "SimpleError: {}", self.message)
    }
}

impl Error for SimpleError {}

fn demonstrate_simple_custom_error() {
    println!("\n简单自定义错误:");
    
    fn validate_age(age: i32) -> Result<i32, SimpleError> {
        if age < 0 {
            Err(SimpleError::new("年龄不能为负数"))
        } else if age > 150 {
            Err(SimpleError::new("年龄不能超过150岁"))
        } else {
            Ok(age)
        }
    }
    
    let test_ages = vec![-5, 25, 200];
    
    for age in test_ages {
        match validate_age(age) {
            Ok(valid_age) => println!("有效年龄: {}", valid_age),
            Err(error) => println!("年龄验证失败: {}", error),
        }
    }
}

// 枚举错误类型
#[derive(Debug, Clone)]
enum ValidationError {
    TooShort { min_length: usize, actual_length: usize },
    TooLong { max_length: usize, actual_length: usize },
    InvalidCharacter { character: char, position: usize },
    Empty,
    InvalidFormat(String),
}

impl fmt::Display for ValidationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ValidationError::TooShort { min_length, actual_length } => {
                write!(f, "字符串太短:需要至少{}个字符,实际{}个字符", 
                       min_length, actual_length)
            }
            ValidationError::TooLong { max_length, actual_length } => {
                write!(f, "字符串太长:最多{}个字符,实际{}个字符", 
                       max_length, actual_length)
            }
            ValidationError::InvalidCharacter { character, position } => {
                write!(f, "无效字符 '{}' 在位置 {}", character, position)
            }
            ValidationError::Empty => {
                write!(f, "字符串不能为空")
            }
            ValidationError::InvalidFormat(msg) => {
                write!(f, "格式无效: {}", msg)
            }
        }
    }
}

impl Error for ValidationError {}

fn demonstrate_enum_error() {
    println!("\n枚举错误类型:");
    
    fn validate_username(username: &str) -> Result<String, ValidationError> {
        if username.is_empty() {
            return Err(ValidationError::Empty);
        }
        
        if username.len() < 3 {
            return Err(ValidationError::TooShort {
                min_length: 3,
                actual_length: username.len(),
            });
        }
        
        if username.len() > 20 {
            return Err(ValidationError::TooLong {
                max_length: 20,
                actual_length: username.len(),
            });
        }
        
        for (i, ch) in username.chars().enumerate() {
            if !ch.is_alphanumeric() && ch != '_' {
                return Err(ValidationError::InvalidCharacter {
                    character: ch,
                    position: i,
                });
            }
        }
        
        if username.chars().next().unwrap().is_ascii_digit() {
            return Err(ValidationError::InvalidFormat(
                "用户名不能以数字开头".to_string()
            ));
        }
        
        Ok(username.to_string())
    }
    
    let test_usernames = vec![
        "",
        "ab",
        "this_is_a_very_long_username_that_exceeds_limit",
        "user@name",
        "123user",
        "valid_user",
    ];
    
    for username in test_usernames {
        match validate_username(username) {
            Ok(valid) => println!("有效用户名: '{}'", valid),
            Err(error) => println!("用户名 '{}' 验证失败: {}", username, error),
        }
    }
}

// 复合错误类型
#[derive(Debug)]
enum AppError {
    Io(io::Error),
    Parse(ParseIntError),
    Validation(ValidationError),
    Network { code: u16, message: String },
    Database { table: String, operation: String, cause: String },
}

impl fmt::Display for AppError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            AppError::Io(err) => write!(f, "IO错误: {}", err),
            AppError::Parse(err) => write!(f, "解析错误: {}", err),
            AppError::Validation(err) => write!(f, "验证错误: {}", err),
            AppError::Network { code, message } => {
                write!(f, "网络错误 {}: {}", code, message)
            }
            AppError::Database { table, operation, cause } => {
                write!(f, "数据库错误: 在表 '{}' 执行 '{}' 操作时失败: {}", 
                       table, operation, cause)
            }
        }
    }
}

impl Error for AppError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            AppError::Io(err) => Some(err),
            AppError::Parse(err) => Some(err),
            AppError::Validation(err) => Some(err),
            _ => None,
        }
    }
}

// 实现From trait进行自动转换
impl From<io::Error> for AppError {
    fn from(error: io::Error) -> Self {
        AppError::Io(error)
    }
}

impl From<ParseIntError> for AppError {
    fn from(error: ParseIntError) -> Self {
        AppError::Parse(error)
    }
}

impl From<ValidationError> for AppError {
    fn from(error: ValidationError) -> Self {
        AppError::Validation(error)
    }
}

fn demonstrate_error_trait() {
    println!("\nError trait实现:");
    
    fn process_user_data(data: &str) -> Result<(String, i32), AppError> {
        let parts: Vec<&str> = data.split(',').collect();
        
        if parts.len() != 2 {
            return Err(AppError::Validation(ValidationError::InvalidFormat(
                "数据格式应为 'username,age'".to_string()
            )));
        }
        
        let username = validate_username(parts[0].trim())?;
        let age = parts[1].trim().parse::<i32>()?;
        
        if age < 0 || age > 150 {
            return Err(AppError::Validation(ValidationError::InvalidFormat(
                "年龄必须在0-150之间".to_string()
            )));
        }
        
        Ok((username, age))
    }
    
    fn validate_username(username: &str) -> Result<String, ValidationError> {
        if username.is_empty() {
            return Err(ValidationError::Empty);
        }
        
        if username.len() < 3 {
            return Err(ValidationError::TooShort {
                min_length: 3,
                actual_length: username.len(),
            });
        }
        
        Ok(username.to_string())
    }
    
    let test_data = vec![
        "alice,25",
        "bob",
        "ab,30",
        "charlie,abc",
        "diana,200",
    ];
    
    for data in test_data {
        match process_user_data(data) {
            Ok((username, age)) => println!("处理成功: 用户 '{}', 年龄 {}", username, age),
            Err(error) => {
                println!("处理失败: {}", error);
                
                // 显示错误链
                let mut source = error.source();
                while let Some(err) = source {
                    println!("  原因: {}", err);
                    source = err.source();
                }
            }
        }
    }
}

fn demonstrate_error_chain() {
    println!("\n错误链:");
    
    fn simulate_network_request() -> Result<String, AppError> {
        // 模拟网络错误
        Err(AppError::Network {
            code: 404,
            message: "资源未找到".to_string(),
        })
    }
    
    fn simulate_database_operation() -> Result<String, AppError> {
        // 模拟数据库错误
        Err(AppError::Database {
            table: "users".to_string(),
            operation: "SELECT".to_string(),
            cause: "连接超时".to_string(),
        })
    }
    
    fn complex_operation() -> Result<String, AppError> {
        // 尝试网络请求
        let _network_result = simulate_network_request()?;
        
        // 尝试数据库操作
        let _db_result = simulate_database_operation()?;
        
        Ok("操作成功".to_string())
    }
    
    match complex_operation() {
        Ok(result) => println!("复杂操作成功: {}", result),
        Err(error) => {
            println!("复杂操作失败: {}", error);
            
            // 根据错误类型进行不同处理
            match error {
                AppError::Network { code, .. } if code == 404 => {
                    println!("  -> 建议: 检查请求URL是否正确");
                }
                AppError::Database { table, .. } => {
                    println!("  -> 建议: 检查数据库连接和表 '{}' 是否存在", table);
                }
                _ => {
                    println!("  -> 建议: 检查系统状态");
                }
            }
        }
    }
}
rustc custom_errors.rs && ./custom_errors

8.3.2 错误处理最佳实践

use std::error::Error;
use std::fmt;
use std::fs::File;
use std::io::{self, Read};

fn main() {
    println!("🏆 错误处理最佳实践");
    println!("==================");
    
    demonstrate_error_design_principles();
    demonstrate_error_context();
    demonstrate_error_recovery();
    demonstrate_logging_and_monitoring();
}

// 错误设计原则
fn demonstrate_error_design_principles() {
    println!("\n错误设计原则:");
    
    // 1. 使用具体的错误类型
    #[derive(Debug)]
    enum ConfigError {
        FileNotFound(String),
        InvalidFormat { line: usize, reason: String },
        MissingField(String),
        InvalidValue { field: String, value: String, expected: String },
    }
    
    impl fmt::Display for ConfigError {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match self {
                ConfigError::FileNotFound(path) => {
                    write!(f, "配置文件未找到: {}", path)
                }
                ConfigError::InvalidFormat { line, reason } => {
                    write!(f, "配置文件格式错误 (行 {}): {}", line, reason)
                }
                ConfigError::MissingField(field) => {
                    write!(f, "缺少必需字段: {}", field)
                }
                ConfigError::InvalidValue { field, value, expected } => {
                    write!(f, "字段 '{}' 的值 '{}' 无效,期望: {}", field, value, expected)
                }
            }
        }
    }
    
    impl Error for ConfigError {}
    
    // 2. 提供有用的错误信息
    fn parse_config(content: &str) -> Result<Config, ConfigError> {
        let mut config = Config::default();
        
        for (line_num, line) in content.lines().enumerate() {
            let line = line.trim();
            if line.is_empty() || line.starts_with('#') {
                continue;
            }
            
            let parts: Vec<&str> = line.split('=').collect();
            if parts.len() != 2 {
                return Err(ConfigError::InvalidFormat {
                    line: line_num + 1,
                    reason: "每行应该是 'key=value' 格式".to_string(),
                });
            }
            
            let key = parts[0].trim();
            let value = parts[1].trim();
            
            match key {
                "port" => {
                    config.port = value.parse().map_err(|_| {
                        ConfigError::InvalidValue {
                            field: "port".to_string(),
                            value: value.to_string(),
                            expected: "有效的端口号 (1-65535)".to_string(),
                        }
                    })?;
                    
                    if config.port == 0 || config.port > 65535 {
                        return Err(ConfigError::InvalidValue {
                            field: "port".to_string(),
                            value: value.to_string(),
                            expected: "1-65535之间的数字".to_string(),
                        });
                    }
                }
                "host" => {
                    if value.is_empty() {
                        return Err(ConfigError::InvalidValue {
                            field: "host".to_string(),
                            value: value.to_string(),
                            expected: "非空主机名".to_string(),
                        });
                    }
                    config.host = value.to_string();
                }
                "debug" => {
                    config.debug = value.parse().map_err(|_| {
                        ConfigError::InvalidValue {
                            field: "debug".to_string(),
                            value: value.to_string(),
                            expected: "true 或 false".to_string(),
                        }
                    })?;
                }
                _ => {
                    println!("警告: 未知配置项 '{}'", key);
                }
            }
        }
        
        // 验证必需字段
        if config.host.is_empty() {
            return Err(ConfigError::MissingField("host".to_string()));
        }
        
        Ok(config)
    }
    
    #[derive(Debug, Default)]
    struct Config {
        host: String,
        port: u16,
        debug: bool,
    }
    
    // 测试配置解析
    let test_configs = vec![
        "host=localhost\nport=8080\ndebug=true",
        "host=\nport=8080", // 空主机名
        "port=abc", // 无效端口
        "host=localhost\nport=99999", // 端口超出范围
        "invalid_line", // 格式错误
    ];
    
    for (i, config_content) in test_configs.iter().enumerate() {
        println!("\n测试配置 {}:", i + 1);
        match parse_config(config_content) {
            Ok(config) => println!("  解析成功: {:?}", config),
            Err(error) => println!("  解析失败: {}", error),
        }
    }
}

// 错误上下文
fn demonstrate_error_context() {
    println!("\n错误上下文:");
    
    // 使用Result扩展提供上下文
    trait ResultExt<T, E> {
        fn with_context<F>(self, f: F) -> Result<T, ContextError<E>>
        where
            F: FnOnce() -> String;
    }
    
    impl<T, E> ResultExt<T, E> for Result<T, E> {
        fn with_context<F>(self, f: F) -> Result<T, ContextError<E>>
        where
            F: FnOnce() -> String,
        {
            self.map_err(|error| ContextError {
                context: f(),
                source: error,
            })
        }
    }
    
    #[derive(Debug)]
    struct ContextError<E> {
        context: String,
        source: E,
    }
    
    impl<E: fmt::Display> fmt::Display for ContextError<E> {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}: {}", self.context, self.source)
        }
    }
    
    impl<E: Error + 'static> Error for ContextError<E> {
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            Some(&self.source)
        }
    }
    
    // 使用上下文的函数
    fn read_user_config(user_id: u32) -> Result<String, ContextError<io::Error>> {
        let config_path = format!("user_{}.conf", user_id);
        
        std::fs::read_to_string(&config_path)
            .with_context(|| format!("读取用户 {} 的配置文件 '{}' 时失败", user_id, config_path))
    }
    
    fn process_user_data(user_id: u32) -> Result<String, ContextError<ContextError<io::Error>>> {
        let config = read_user_config(user_id)
            .with_context(|| format!("处理用户 {} 的数据时失败", user_id))?;
        
        Ok(format!("处理了用户 {} 的配置: {} 字符", user_id, config.len()))
    }
    
    // 测试上下文错误
    match process_user_data(123) {
        Ok(result) => println!("处理成功: {}", result),
        Err(error) => {
            println!("处理失败: {}", error);
            
            // 显示完整的错误链
            let mut source = error.source();
            let mut level = 1;
            while let Some(err) = source {
                println!("  级别 {}: {}", level, err);
                source = err.source();
                level += 1;
            }
        }
    }
}

// 错误恢复策略
fn demonstrate_error_recovery() {
    println!("\n错误恢复策略:");
    
    // 1. 重试机制
    fn retry_operation<F, T, E>(mut operation: F, max_attempts: usize) -> Result<T, E>
    where
        F: FnMut() -> Result<T, E>,
    {
        let mut attempts = 0;
        loop {
            attempts += 1;
            match operation() {
                Ok(result) => return Ok(result),
                Err(error) => {
                    if attempts >= max_attempts {
                        return Err(error);
                    }
                    println!("  尝试 {} 失败,重试中...", attempts);
                    std::thread::sleep(std::time::Duration::from_millis(100));
                }
            }
        }
    }
    
    // 模拟不稳定的操作
    fn unstable_operation() -> Result<String, String> {
        use std::sync::atomic::{AtomicUsize, Ordering};
        static COUNTER: AtomicUsize = AtomicUsize::new(0);
        
        let count = COUNTER.fetch_add(1, Ordering::SeqCst);
        if count < 2 {
            Err(format!("操作失败 (尝试 {})", count + 1))
        } else {
            Ok("操作成功".to_string())
        }
    }
    
    match retry_operation(unstable_operation, 3) {
        Ok(result) => println!("重试成功: {}", result),
        Err(error) => println!("重试失败: {}", error),
    }
    
    // 2. 降级策略
    fn get_data_with_fallback(primary: bool) -> Result<String, String> {
        if primary {
            get_primary_data().or_else(|_| {
                println!("  主数据源失败,使用备用数据源");
                get_fallback_data()
            })
        } else {
            get_fallback_data()
        }
    }
    
    fn get_primary_data() -> Result<String, String> {
        Err("主数据源不可用".to_string())
    }
    
    fn get_fallback_data() -> Result<String, String> {
        Ok("备用数据".to_string())
    }
    
    match get_data_with_fallback(true) {
        Ok(data) => println!("获取数据成功: {}", data),
        Err(error) => println!("获取数据失败: {}", error),
    }
    
    // 3. 部分失败处理
    fn process_batch(items: Vec<&str>) -> (Vec<String>, Vec<String>) {
        let mut successes = Vec::new();
        let mut failures = Vec::new();
        
        for item in items {
            match process_item(item) {
                Ok(result) => successes.push(result),
                Err(error) => failures.push(format!("处理 '{}' 失败: {}", item, error)),
            }
        }
        
        (successes, failures)
    }
    
    fn process_item(item: &str) -> Result<String, String> {
        if item.is_empty() {
            Err("空项目".to_string())
        } else if item.len() > 10 {
            Err("项目太长".to_string())
        } else {
            Ok(format!("已处理: {}", item))
        }
    }
    
    let items = vec!["item1", "", "item3", "very_long_item_name", "item5"];
    let (successes, failures) = process_batch(items);
    
    println!("批处理结果:");
    println!("  成功: {:?}", successes);
    println!("  失败: {:?}", failures);
}

// 日志和监控
fn demonstrate_logging_and_monitoring() {
    println!("\n日志和监控:");
    
    // 简单的日志记录
    #[derive(Debug)]
    enum LogLevel {
        Error,
        Warn,
        Info,
        Debug,
    }
    
    fn log(level: LogLevel, message: &str) {
        let timestamp = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_secs();
        println!("[{}] {:?}: {}", timestamp, level, message);
    }
    
    // 带监控的操作
    fn monitored_operation(input: &str) -> Result<String, String> {
        log(LogLevel::Info, &format!("开始处理输入: {}", input));
        
        let start_time = std::time::Instant::now();
        
        let result = if input.is_empty() {
            let error = "输入为空";
            log(LogLevel::Error, error);
            Err(error.to_string())
        } else if input.len() > 100 {
            let error = "输入太长";
            log(LogLevel::Warn, &format!("{}: {} 字符", error, input.len()));
            Err(error.to_string())
        } else {
            let result = format!("处理结果: {}", input.to_uppercase());
            log(LogLevel::Info, &format!("处理成功: {} 字符", input.len()));
            Ok(result)
        };
        
        let duration = start_time.elapsed();
        log(LogLevel::Debug, &format!("操作耗时: {:?}", duration));
        
        result
    }
    
    // 测试监控
    let test_inputs = vec![
        "hello",
        "",
        &"x".repeat(150),
    ];
    
    for input in test_inputs {
        match monitored_operation(input) {
            Ok(result) => println!("操作成功: {}", result),
            Err(error) => println!("操作失败: {}", error),
        }
        println!();
    }
    
    // 错误统计
    use std::collections::HashMap;
    
    #[derive(Debug)]
    struct ErrorStats {
        counts: HashMap<String, usize>,
        total: usize,
    }
    
    impl ErrorStats {
        fn new() -> Self {
            ErrorStats {
                counts: HashMap::new(),
                total: 0,
            }
        }
        
        fn record_error(&mut self, error_type: &str) {
            *self.counts.entry(error_type.to_string()).or_insert(0) += 1;
            self.total += 1;
        }
        
        fn report(&self) {
            println!("错误统计报告:");
            println!("  总错误数: {}", self.total);
            for (error_type, count) in &self.counts {
                let percentage = (*count as f64 / self.total as f64) * 100.0;
                println!("  {}: {} ({:.1}%)", error_type, count, percentage);
            }
        }
    }
    
    let mut stats = ErrorStats::new();
    
    // 模拟一些错误
    let errors = vec![
        "网络错误", "解析错误", "网络错误", "验证错误",
        "网络错误", "解析错误", "数据库错误",
    ];
    
    for error in errors {
        stats.record_error(error);
    }
    
    stats.report();
}
rustc error_best_practices.rs && ./error_best_practices

8.4 综合示例:文件处理系统

use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::fs::{self, File};
use std::io::{self, BufRead, BufReader, Write};
use std::path::{Path, PathBuf};

fn main() {
    println!("📁 文件处理系统");
    println!("===============");
    
    let mut processor = FileProcessor::new();
    
    // 创建测试文件
    setup_test_files().unwrap_or_else(|e| {
        eprintln!("设置测试文件失败: {}", e);
    });
    
    // 处理文件
    match processor.process_directory("test_files") {
        Ok(report) => {
            println!("\n处理完成!");
            report.display();
        }
        Err(error) => {
            eprintln!("处理失败: {}", error);
            
            // 显示错误链
            let mut source = error.source();
            while let Some(err) = source {
                eprintln!("  原因: {}", err);
                source = err.source();
            }
        }
    }
    
    // 清理测试文件
    cleanup_test_files().unwrap_or_else(|e| {
        eprintln!("清理测试文件失败: {}", e);
    });
}

// 自定义错误类型
#[derive(Debug)]
enum ProcessingError {
    Io(io::Error),
    InvalidFormat { file: PathBuf, line: usize, reason: String },
    UnsupportedFileType(String),
    ProcessingFailed { file: PathBuf, reason: String },
    ConfigError(String),
}

impl fmt::Display for ProcessingError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ProcessingError::Io(err) => write!(f, "IO错误: {}", err),
            ProcessingError::InvalidFormat { file, line, reason } => {
                write!(f, "文件 {:?} 第 {} 行格式无效: {}", file, line, reason)
            }
            ProcessingError::UnsupportedFileType(ext) => {
                write!(f, "不支持的文件类型: {}", ext)
            }
            ProcessingError::ProcessingFailed { file, reason } => {
                write!(f, "处理文件 {:?} 失败: {}", file, reason)
            }
            ProcessingError::ConfigError(msg) => {
                write!(f, "配置错误: {}", msg)
            }
        }
    }
}

impl Error for ProcessingError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            ProcessingError::Io(err) => Some(err),
            _ => None,
        }
    }
}

impl From<io::Error> for ProcessingError {
    fn from(error: io::Error) -> Self {
        ProcessingError::Io(error)
    }
}

// 文件处理器
struct FileProcessor {
    config: ProcessingConfig,
    stats: ProcessingStats,
}

#[derive(Debug)]
struct ProcessingConfig {
    supported_extensions: Vec<String>,
    max_file_size: u64,
    output_directory: PathBuf,
}

impl Default for ProcessingConfig {
    fn default() -> Self {
        ProcessingConfig {
            supported_extensions: vec!["txt".to_string(), "csv".to_string(), "log".to_string()],
            max_file_size: 10 * 1024 * 1024, // 10MB
            output_directory: PathBuf::from("processed"),
        }
    }
}

#[derive(Debug, Default)]
struct ProcessingStats {
    files_processed: usize,
    files_failed: usize,
    lines_processed: usize,
    errors: Vec<String>,
}

#[derive(Debug)]
struct ProcessingReport {
    stats: ProcessingStats,
    duration: std::time::Duration,
}

impl ProcessingReport {
    fn display(&self) {
        println!("处理报告:");
        println!("  处理时间: {:?}", self.duration);
        println!("  成功处理文件: {}", self.stats.files_processed);
        println!("  失败文件: {}", self.stats.files_failed);
        println!("  总处理行数: {}", self.stats.lines_processed);
        
        if !self.stats.errors.is_empty() {
            println!("  错误列表:");
            for (i, error) in self.stats.errors.iter().enumerate() {
                println!("    {}: {}", i + 1, error);
            }
        }
        
        let total_files = self.stats.files_processed + self.stats.files_failed;
        if total_files > 0 {
            let success_rate = (self.stats.files_processed as f64 / total_files as f64) * 100.0;
            println!("  成功率: {:.1}%", success_rate);
        }
    }
}

impl FileProcessor {
    fn new() -> Self {
        FileProcessor {
            config: ProcessingConfig::default(),
            stats: ProcessingStats::default(),
        }
    }
    
    fn process_directory(&mut self, dir_path: &str) -> Result<ProcessingReport, ProcessingError> {
        let start_time = std::time::Instant::now();
        
        // 创建输出目录
        fs::create_dir_all(&self.config.output_directory)?;
        
        // 读取目录
        let entries = fs::read_dir(dir_path)?;
        
        for entry in entries {
            let entry = entry?;
            let path = entry.path();
            
            if path.is_file() {
                match self.process_file(&path) {
                    Ok(_) => {
                        self.stats.files_processed += 1;
                        println!("✓ 处理成功: {:?}", path);
                    }
                    Err(error) => {
                        self.stats.files_failed += 1;
                        let error_msg = format!("处理 {:?} 失败: {}", path, error);
                        self.stats.errors.push(error_msg.clone());
                        eprintln!("✗ {}", error_msg);
                    }
                }
            }
        }
        
        let duration = start_time.elapsed();
        
        Ok(ProcessingReport {
            stats: std::mem::take(&mut self.stats),
            duration,
        })
    }
    
    fn process_file(&mut self, file_path: &Path) -> Result<(), ProcessingError> {
        // 检查文件扩展名
        let extension = file_path
            .extension()
            .and_then(|ext| ext.to_str())
            .ok_or_else(|| ProcessingError::UnsupportedFileType("无扩展名".to_string()))?;
        
        if !self.config.supported_extensions.contains(&extension.to_lowercase()) {
            return Err(ProcessingError::UnsupportedFileType(extension.to_string()));
        }
        
        // 检查文件大小
        let metadata = fs::metadata(file_path)?;
        if metadata.len() > self.config.max_file_size {
            return Err(ProcessingError::ProcessingFailed {
                file: file_path.to_path_buf(),
                reason: format!("文件太大: {} 字节", metadata.len()),
            });
        }
        
        // 根据文件类型处理
        match extension.to_lowercase().as_str() {
            "txt" => self.process_text_file(file_path),
            "csv" => self.process_csv_file(file_path),
            "log" => self.process_log_file(file_path),
            _ => Err(ProcessingError::UnsupportedFileType(extension.to_string())),
        }
    }
    
    fn process_text_file(&mut self, file_path: &Path) -> Result<(), ProcessingError> {
        let file = File::open(file_path)?;
        let reader = BufReader::new(file);
        
        let output_path = self.config.output_directory.join(
            format!("{}_processed.txt", 
                    file_path.file_stem().unwrap().to_str().unwrap())
        );
        
        let mut output_file = File::create(&output_path)?;
        let mut line_count = 0;
        
        for (line_num, line_result) in reader.lines().enumerate() {
            let line = line_result?;
            line_count += 1;
            
            // 简单的文本处理:转换为大写并添加行号
            let processed_line = format!("{:04}: {}\n", line_num + 1, line.to_uppercase());
            output_file.write_all(processed_line.as_bytes())?;
        }
        
        self.stats.lines_processed += line_count;
        Ok(())
    }
    
    fn process_csv_file(&mut self, file_path: &Path) -> Result<(), ProcessingError> {
        let file = File::open(file_path)?;
        let reader = BufReader::new(file);
        
        let output_path = self.config.output_directory.join(
            format!("{}_summary.txt", 
                    file_path.file_stem().unwrap().to_str().unwrap())
        );
        
        let mut output_file = File::create(&output_path)?;
        let mut line_count = 0;
        let mut column_stats: HashMap<usize, usize> = HashMap::new();
        
        for (line_num, line_result) in reader.lines().enumerate() {
            let line = line_result?;
            line_count += 1;
            
            let columns: Vec<&str> = line.split(',').collect();
            
            // 验证CSV格式
            if line_num == 0 && columns.is_empty() {
                return Err(ProcessingError::InvalidFormat {
                    file: file_path.to_path_buf(),
                    line: line_num + 1,
                    reason: "CSV文件不能为空".to_string(),
                });
            }
            
            // 统计列数
            *column_stats.entry(columns.len()).or_insert(0) += 1;
        }
        
        // 写入统计信息
        writeln!(output_file, "CSV文件统计: {:?}", file_path)?;
        writeln!(output_file, "总行数: {}", line_count)?;
        writeln!(output_file, "列数分布:")?;
        
        for (col_count, row_count) in column_stats {
            writeln!(output_file, "  {} 列: {} 行", col_count, row_count)?;
        }
        
        self.stats.lines_processed += line_count;
        Ok(())
    }
    
    fn process_log_file(&mut self, file_path: &Path) -> Result<(), ProcessingError> {
        let file = File::open(file_path)?;
        let reader = BufReader::new(file);
        
        let output_path = self.config.output_directory.join(
            format!("{}_analysis.txt", 
                    file_path.file_stem().unwrap().to_str().unwrap())
        );
        
        let mut output_file = File::create(&output_path)?;
        let mut line_count = 0;
        let mut error_count = 0;
        let mut warning_count = 0;
        let mut info_count = 0;
        
        for line_result in reader.lines() {
            let line = line_result?;
            line_count += 1;
            
            let line_lower = line.to_lowercase();
            if line_lower.contains("error") {
                error_count += 1;
            } else if line_lower.contains("warning") || line_lower.contains("warn") {
                warning_count += 1;
            } else if line_lower.contains("info") {
                info_count += 1;
            }
        }
        
        // 写入分析结果
        writeln!(output_file, "日志文件分析: {:?}", file_path)?;
        writeln!(output_file, "总行数: {}", line_count)?;
        writeln!(output_file, "错误行数: {}", error_count)?;
        writeln!(output_file, "警告行数: {}", warning_count)?;
        writeln!(output_file, "信息行数: {}", info_count)?;
        
        let error_rate = if line_count > 0 {
            (error_count as f64 / line_count as f64) * 100.0
        } else {
            0.0
        };
        writeln!(output_file, "错误率: {:.2}%", error_rate)?;
        
        self.stats.lines_processed += line_count;
        Ok(())
    }
}

// 辅助函数
fn setup_test_files() -> Result<(), io::Error> {
    fs::create_dir_all("test_files")?;
    
    // 创建测试文本文件
    fs::write("test_files/sample.txt", "Hello World\nThis is a test file\nWith multiple lines")?;
    
    // 创建测试CSV文件
    fs::write("test_files/data.csv", "name,age,city\nAlice,30,New York\nBob,25,London\nCharlie,35,Tokyo")?;
    
    // 创建测试日志文件
    fs::write("test_files/app.log", 
        "INFO: Application started\nWARNING: Low memory\nERROR: Database connection failed\nINFO: User logged in")?;
    
    // 创建不支持的文件类型
    fs::write("test_files/image.jpg", "fake image data")?;
    
    Ok(())
}

fn cleanup_test_files() -> Result<(), io::Error> {
    if Path::new("test_files").exists() {
        fs::remove_dir_all("test_files")?;
    }
    if Path::new("processed").exists() {
        fs::remove_dir_all("processed")?;
    }
    Ok(())
}
rustc file_processing_system.rs && ./file_processing_system

本章小结

在本章中,我们深入学习了Rust的错误处理机制:

🎯 核心概念

  • 错误处理哲学: 显式、类型安全、强制处理
  • Option类型: 处理可能不存在的值
  • Result类型: 处理可能失败的操作
  • ?操作符: 简化错误传播

🛠️ 实用技能

  • 使用matchif letwhile let处理错误
  • 创建自定义错误类型
  • 实现错误转换和链式处理
  • 应用错误恢复策略

📋 最佳实践

  • 提供有意义的错误信息
  • 使用具体的错误类型
  • 实现适当的错误恢复机制
  • 记录和监控错误

🔧 高级特性

  • 错误上下文和错误链
  • 重试和降级策略
  • 批处理中的部分失败处理
  • 错误统计和分析

下一章预告

下一章我们将学习泛型和特征,探索Rust的类型系统如何提供代码复用和抽象能力:

  • 🔄 泛型函数和结构体
  • 🎭 特征定义和实现
  • 🔗 特征边界和关联类型
  • 🏗️ 高级特征模式
  • 🎯 实战:构建通用数据结构

练习题

基础练习

  1. 创建一个函数,安全地将字符串转换为数字,处理所有可能的错误情况
  2. 实现一个简单的配置文件解析器,使用自定义错误类型
  3. 编写一个函数,读取多个文件并收集所有成功和失败的结果

进阶练习

  1. 实现一个带重试机制的网络请求模拟器
  2. 创建一个错误恢复系统,支持多种降级策略
  3. 设计一个日志分析工具,统计不同类型的错误

挑战练习

  1. 实现一个完整的错误处理框架,包括上下文、重试、监控
  2. 创建一个数据验证库,支持链式验证和详细错误报告
  3. 设计一个分布式系统的错误处理策略,处理网络分区和服务降级

通过这些练习,你将掌握Rust错误处理的精髓,能够构建健壮可靠的应用程序!