MST

星途 面试题库

面试题:Rust中unwrap_or_else和expect在复杂场景下错误处理的差异

在一个文件读取操作中,使用`std::fs::read_to_string`函数读取文件内容,该函数返回`Result<String, std::io::Error>`。假设你需要对可能出现的错误进行特定处理,并且要在日志中记录错误信息。请分别用`unwrap_or_else`和`expect`实现这个需求,并详细阐述在这种场景下,两者在错误处理、代码可读性以及可维护性方面的差异。
38.0万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

使用 unwrap_or_else 实现

use std::fs;
use std::io;

fn read_file_with_unwrap_or_else(file_path: &str) -> String {
    fs::read_to_string(file_path).unwrap_or_else(|error| {
        log_error(&error);
        String::new()
    })
}

fn log_error(error: &io::Error) {
    println!("Error reading file: {}", error);
}

使用 expect 实现

use std::fs;
use std::io;

fn read_file_with_expect(file_path: &str) -> String {
    fs::read_to_string(file_path).expect(&format!("Error reading file: {}", log_error_and_get_msg()))
}

fn log_error_and_get_msg() -> String {
    let error_msg = "Failed to read file".to_string();
    println!("{}", error_msg);
    error_msg
}

差异分析

  • 错误处理
    • unwrap_or_else:允许开发者自定义在错误发生时的返回值。这在希望程序在出错时仍能继续运行,并返回一个默认值的场景下很有用。例如,在读取配置文件时,如果文件不存在,可以返回一个默认配置。
    • expect:在错误发生时直接使程序 panic,并附带一个自定义的错误信息。适用于错误情况不应该发生,一旦发生就是严重问题,需要程序立即停止的场景,如初始化关键配置文件失败。
  • 代码可读性
    • unwrap_or_else:代码相对冗长,因为需要定义错误处理逻辑。但它清晰地表明了在错误发生时程序的替代行为,可读性较好,尤其是对于复杂的错误处理逻辑。
    • expect:代码简洁明了,直接表达了对操作成功的预期。但如果错误处理逻辑复杂,expect 中的错误信息构造可能会变得冗长,降低可读性。
  • 可维护性
    • unwrap_or_else:由于自定义错误处理逻辑清晰,当需求变化,如需要更改默认返回值或错误处理方式时,维护成本较低。
    • expect:如果只是简单的 panic 并附带错误信息,维护简单。但如果错误处理逻辑变得复杂,如需要记录日志并执行其他清理操作,expect 方式可能需要较大改动,维护成本相对较高。