面试题答案
一键面试设计思路
- 定义错误 trait:创建一个基础的 trait 来描述数据库错误,不同数据库的具体错误类型都实现这个 trait。这样通过 trait 对象,调用者可以以统一的方式处理不同数据库错误。
- 为不同数据库实现具体错误类型:每个数据库(如 SQLite、PostgreSQL)都有自己的错误类型,这些类型实现上述定义的错误 trait。
- 使用泛型和 trait 对象:在数据库操作库的接口函数中,通过泛型来接收不同的数据库错误类型,并使用 trait 对象来进行错误处理,从而实现统一的错误处理逻辑。
核心代码示例(以 Rust 语言为例)
// 定义基础的数据库错误 trait
trait DatabaseError: std::fmt::Debug + std::fmt::Display {
// 可以在这里定义一些通用的错误方法
fn error_message(&self) -> String;
}
// SQLite 特定错误类型
struct SQLiteError {
message: String,
}
impl DatabaseError for SQLiteError {
fn error_message(&self) -> String {
self.message.clone()
}
}
impl std::fmt::Debug for SQLiteError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "SQLiteError: {}", self.message)
}
}
impl std::fmt::Display for SQLiteError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.message)
}
}
// PostgreSQL 特定错误类型
struct PostgreSQLError {
message: String,
}
impl DatabaseError for PostgreSQLError {
fn error_message(&self) -> String {
self.message.clone()
}
}
impl std::fmt::Debug for PostgreSQLError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "PostgreSQLError: {}", self.message)
}
}
impl std::fmt::Display for PostgreSQLError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.message)
}
}
// 数据库操作函数示例,使用泛型和 trait 对象处理错误
fn execute_query<T: DatabaseError>(query: &str) -> Result<(), Box<dyn DatabaseError>> {
// 这里只是模拟不同数据库的错误返回
if query.contains("sqlite") {
Err(Box::new(SQLiteError {
message: "SQLite specific error".to_string(),
}))
} else if query.contains("postgresql") {
Err(Box::new(PostgreSQLError {
message: "PostgreSQL specific error".to_string(),
}))
} else {
Ok(())
}
}
调用示例:
fn main() {
match execute_query("select * from users sqlite") {
Ok(_) => println!("Query executed successfully"),
Err(e) => println!("Error: {}", e.error_message()),
}
}