随着项目的进展,关于Rust的故事又翻开了新的一页,今天来到了服务器端的开发场景,发现错误处理中的错误类型转换有必要分享一下。
Rust抽象出来了Result
在api请求的框架中,我把返回类型定义成了Result
,即错误类型是rocket::response::status::Custom\
。
在tokio_postgres中,直接使用tokio_postgres::error::Error
。
即如果要处理错误,就必须将tokio_postgres::error::Error
转换成rocket::response::status::Custom\
。那么我们从下面的原理开始,逐一领略Rust的错误处理方式,通过对比找到最合适的方式吧。
对错误的处理,Rust有3种可选的方式
下面我结合场景,逐一演示各种方式是如何处理错误的。
下面的代码中涉及到2个模块(文件)。/src/routes/notes.rs
是路由层,负责将api请求导向合适的service。/src/services/note_books.rs
是service层,负责业务逻辑和数据持久化的处理。这里的逻辑也很简单,就是route层调用service层,将数据写入到数据库中。
src/routes/notes.rs
#[post("/api/notes", format = "application/json", data = "" )]
pub async fn post_notes(note: Json<Note>) -> Result<(), rocket::response::status::Custom<String>> {
insert_or_update_note(¬e.into_inner()).await
}
/src/services/note_book.rs
pub async fn insert_or_update_note(
note: &Note,
) -> Result<(), rocket::response::status::Custom<String>> {
let (client, connection) = match connect(
"host=localhost dbname=notes_db user=postgres port=5432",
NoTls,
)
.await
{
Ok(res) => res,
Err(err) => {
return Err(rocket::response::status::Custom(
rocket::http::Status::ExpectationFailed,
format!("{}", err),
));
}
};
...
match client
.execute(
"insert into notes (id, title, content) values($1, $2, $3);",
&[&get_system_seconds(), ¬e.title, ¬e.content],