使用 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
方式可能需要较大改动,维护成本相对较高。