面试题答案
一键面试- 定义自定义错误类型
MyError
:use std::fmt; #[derive(Debug)] enum MyError { FileReadError(String), NetworkConnectionError(String), } impl fmt::Display for MyError { fn fmt(&self, f: &mut fmt::DisplayFormatter<'_>) -> fmt::Result { match self { MyError::FileReadError(msg) => write!(f, "File read error: {}", msg), MyError::NetworkConnectionError(msg) => write!(f, "Network connection error: {}", msg), } } } impl std::error::Error for MyError {}
- 编写返回
Result<T, MyError>
类型的函数:fn my_function() -> Result<String, MyError> { // 模拟不同的错误来源 let is_file_error = true; if is_file_error { Err(MyError::FileReadError("Failed to read file".to_string())) } else { Err(MyError::NetworkConnectionError("Failed to connect to network".to_string())) } }
- 错误类型转换及与
Result
深度集成:- 错误类型转换:可以通过实现
From
trait 来进行错误类型转换。例如,如果要将标准库的io::Error
转换为MyError::FileReadError
,可以这样实现:
impl From<std::io::Error> for MyError { fn from(err: std::io::Error) -> Self { MyError::FileReadError(err.to_string()) } }
- 与
Result
深度集成:Result
类型本身就是为处理可能的错误而设计的。在函数中返回Result<T, MyError>
,可以使用?
操作符来方便地传播错误。例如:
这里use std::fs::read_to_string; fn read_file() -> Result<String, MyError> { let content = read_to_string("nonexistent_file.txt")?; Ok(content) }
read_to_string
返回Result<String, std::io::Error>
,由于我们实现了From<std::io::Error> for MyError
,?
操作符会自动将io::Error
转换为MyError
并传播出去。 - 错误类型转换:可以通过实现
- 优势和适用场景:
- 优势:
- 更具针对性:自定义错误类型
MyError
可以更准确地反映应用程序特定的错误情况,相比io::Error
等通用错误类型,代码阅读者能更快理解错误来源和性质。 - 更好的封装:将应用程序相关的错误封装在自定义错误类型中,避免暴露过多底层库的错误细节,提高代码的稳定性和可维护性。
- 更具针对性:自定义错误类型
- 适用场景:
- 特定领域应用:在特定领域的应用程序,如游戏开发、金融系统等,自定义错误类型可以更好地表示该领域特有的错误,而
io::Error
等通用错误类型不足以准确描述。 - 库开发:当开发一个库时,自定义错误类型可以提供更友好的错误接口,隐藏库内部使用的底层库错误,只向用户暴露库相关的错误。
- 特定领域应用:在特定领域的应用程序,如游戏开发、金融系统等,自定义错误类型可以更好地表示该领域特有的错误,而
- 优势: