面试题答案
一键面试use std::fs::File;
use std::io::{self, Read};
use serde_json::{self, Value};
// 自定义运行时错误
#[derive(Debug)]
enum MyError {
FileNotFound,
JsonParseError(serde_json::Error),
}
impl std::fmt::Display for MyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MyError::FileNotFound => write!(f, "文件不存在"),
MyError::JsonParseError(e) => write!(f, "JSON解析错误: {}", e),
}
}
}
impl std::error::Error for MyError {}
fn read_json_file(file_path: &str) -> Result<Value, MyError> {
let mut file = match File::open(file_path) {
Ok(file) => file,
Err(_) => return Err(MyError::FileNotFound),
};
let mut contents = String::new();
match file.read_to_string(&mut contents) {
Ok(_) => (),
Err(e) => return Err(MyError::JsonParseError(serde_json::Error::custom(format!("读取文件错误: {}", e)))),
};
match serde_json::from_str(&contents) {
Ok(value) => Ok(value),
Err(e) => Err(MyError::JsonParseError(e)),
}
}
Result
类型处理运行时错误的说明
- 错误传播:
- 在
read_json_file
函数中,File::open
可能会因为文件不存在等I/O错误而失败。这里使用match
语句处理Result
,如果File::open
返回Err
,直接返回Err(MyError::FileNotFound)
,将错误传播给调用者。 file.read_to_string
也可能失败,同样使用match
处理Result
,如果失败则构造一个自定义的serde_json::Error
并返回Err
。serde_json::from_str
用于将字符串解析为Value
,如果解析失败,返回Err(MyError::JsonParseError(e))
,其中e
是serde_json::Error
。
- 在
- 错误处理:
- 调用者在调用
read_json_file
函数时,会得到一个Result<Value, MyError>
。调用者可以使用match
语句处理这个Result
:
- 调用者在调用
fn main() {
let result = read_json_file("path/to/your/file.json");
match result {
Ok(value) => println!("解析成功: {:?}", value),
Err(e) => println!("错误: {}", e),
}
}
- 或者使用 `unwrap` 或 `expect` 等方法,`unwrap` 在遇到 `Err` 时会直接 `panic!`,`expect` 可以提供自定义的 `panic!` 信息。不过在实际生产代码中,通常更建议使用 `match` 或 `if let` 来优雅地处理错误,而不是直接 `panic!`。例如:
fn main() {
let value = read_json_file("path/to/your/file.json").expect("读取并解析JSON文件失败");
println!("解析成功: {:?}", value);
}
这种方式适用于在开发过程中快速定位错误,或者在确保不会出现错误的情况下使用。但在生产环境中,建议更稳健的错误处理方式。