面试题答案
一键面试设计思路
- 定义基础错误类型:
- 创建一个基础的错误枚举,用于包含所有不同模块的错误类型。
- 使用
std::error::Error
trait 来为这些错误类型提供错误处理的基本功能。
- 错误链模式:
- 利用
thiserror
和anyhow
等库来实现错误链模式。thiserror
库用于方便地定义错误枚举,anyhow
库用于简化错误处理和传播。 - 在每个模块中,将具体的错误类型转换为基础错误类型,并可以在传播过程中添加更多上下文信息。
- 利用
- 错误处理与传播:
- 函数可以返回
Result<T, BaseError>
类型,其中BaseError
是我们定义的基础错误类型。 - 上层调用者可以通过
match
语句或?
操作符来处理不同类型的错误。
- 函数可以返回
关键代码示例
- 定义基础错误类型:
use thiserror::Error; #[derive(Error, Debug)] pub enum BaseError { #[error("Database error: {0}")] Database(#[from] DatabaseError), #[error("Network error: {0}")] Network(#[from] NetworkError), } // 数据库模块错误类型 #[derive(Error, Debug)] pub enum DatabaseError { #[error("Connection error")] ConnectionError, #[error("Query error")] QueryError, } // 网络模块错误类型 #[derive(Error, Debug)] pub enum NetworkError { #[error("Connect error")] ConnectError, #[error("Timeout error")] TimeoutError, }
- 数据库模块示例:
pub fn database_operation() -> Result<(), BaseError> { // 模拟数据库操作失败 Err(DatabaseError::ConnectionError.into()) }
- 网络模块示例:
pub fn network_operation() -> Result<(), BaseError> { // 模拟网络操作失败 Err(NetworkError::TimeoutError.into()) }
- 上层调用示例:
fn main() { match database_operation() { Ok(_) => println!("Database operation success"), Err(e) => match e { BaseError::Database(db_err) => match db_err { DatabaseError::ConnectionError => println!("Database connection error"), DatabaseError::QueryError => println!("Database query error"), }, BaseError::Network(_) => println!("Network error"), }, } // 使用?操作符简化错误处理 let result = network_operation()?; }
在上述代码中,我们首先定义了BaseError
枚举,它包含了DatabaseError
和NetworkError
。每个具体的错误类型都实现了std::error::Error
trait 并提供了自定义的错误信息。模块中的函数返回Result<(), BaseError>
类型,上层调用者可以使用match
语句或?
操作符来处理和传播错误。thiserror
库的#[from]
属性使得从具体错误类型到BaseError
的转换更加方便。