MST
星途 面试题库

面试题:Rust自定义错误类型在复杂业务逻辑中的应用

假设你正在开发一个文件处理的Rust程序,该程序需要读取文件内容、解析特定格式的数据并进行一些计算。请设计一套自定义错误类型,能够涵盖文件读取失败(如文件不存在、权限不足)、数据解析失败(格式错误等)以及计算过程中的错误,并且展示如何在函数之间传递和处理这些错误。
32.6万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
use std::fmt;
use std::fs::File;
use std::io::{self, Read};

// 自定义错误类型
#[derive(Debug)]
enum FileProcessError {
    FileReadError(io::Error),
    DataParseError(String),
    CalculationError(String),
}

impl fmt::Display for FileProcessError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FileProcessError::FileReadError(e) => write!(f, "文件读取错误: {}", e),
            FileProcessError::DataParseError(e) => write!(f, "数据解析错误: {}", e),
            FileProcessError::CalculationError(e) => write!(f, "计算错误: {}", e),
        }
    }
}

impl std::error::Error for FileProcessError {}

// 从文件读取内容
fn read_file(file_path: &str) -> Result<String, FileProcessError> {
    let mut file = File::open(file_path).map_err(FileProcessError::FileReadError)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)
      .map_err(FileProcessError::FileReadError)?;
    Ok(contents)
}

// 解析特定格式数据
fn parse_data(data: &str) -> Result<Vec<i32>, FileProcessError> {
    data.split(',')
      .map(|s| s.trim().parse::<i32>())
      .collect::<Result<Vec<i32>, _>>()
      .map_err(|e| FileProcessError::DataParseError(format!("解析数据错误: {}", e)))
}

// 进行计算
fn calculate(data: &[i32]) -> Result<i32, FileProcessError> {
    if data.is_empty() {
        return Err(FileProcessError::CalculationError("数据为空,无法计算".to_string()));
    }
    let sum: i32 = data.iter().sum();
    Ok(sum)
}

fn main() {
    let file_path = "example.txt";
    let result = read_file(file_path)
      .and_then(parse_data)
      .and_then(calculate);

    match result {
        Ok(sum) => println!("计算结果: {}", sum),
        Err(e) => eprintln!("发生错误: {}", e),
    }
}
  1. 自定义错误类型 FileProcessError
    • 它使用 enum 定义,包含了三种错误类型:FileReadError 用于文件读取失败,DataParseError 用于数据解析失败,CalculationError 用于计算过程中的错误。
    • FileProcessError 实现了 fmt::Displaystd::error::Error 特征,以便能方便地打印错误信息和作为错误类型传递。
  2. 文件读取函数 read_file
    • 使用 File::open 打开文件,如果失败,通过 map_errio::Error 转换为 FileProcessError::FileReadError
    • 使用 read_to_string 读取文件内容,同样如果失败,转换为 FileProcessError::FileReadError
  3. 数据解析函数 parse_data
    • 将输入字符串按逗号分割并尝试解析为 i32 类型的数组。
    • 如果解析失败,将错误信息包装为 FileProcessError::DataParseError
  4. 计算函数 calculate
    • 检查数据是否为空,如果为空返回 CalculationError
    • 计算数据总和并返回。
  5. main 函数
    • 通过 and_then 方法将文件读取、数据解析和计算操作串联起来。
    • 使用 match 语句处理最终结果,打印计算结果或错误信息。