error_chain! Chưa bao giờ quản lý error đơn giản đến thế !
TIL
499
Rust
27
White

Giang Nguyen viết ngày 06/04/2017

Tưởng tượng nếu chúng ta code 1 lib, nhưng trong lib đó chúng ta sẽ dùng hàng loạt crate khác nhau, sẽ có rất nhiều error chúng ta cần phải handle, nếu với cách thông thường chúng ta sẽ khai báo 1 enum có nhiều variant error khác nhau như:

extern crate openssl;
extern crate serde_json;

use openssl::error;
use serde_json;

enum VAPIDError {
    OpenSSL(error::ErrorStack),
    ParseJson(serder_json::error::Error),
}

Kế tiếp chúng ta phải convert error từ crate sang enum của ta

use std::from::From;

impl From<error::ErrorStack> for VAPIDError {
  fn from(e: error::ErrorStack) -> Self {
     VAPIDError::OpenSSL(e)
  }
}

impl From<serder_json::error::Error> for VAPIDError {
  fn from(e: serder_json::error::Error) -> Self {
     VAPIDError::ParseJson(e)
  }
}

Nếu chúng ta có trên 10 crate thì thế nào chúng ta phải lặp lại việc trên dẫn đến việc quản lý rất khó khăn, nếu chúng ta tự khai báo error, chúng ta phải thực hiện thêm việc implement 2 trait std::fmt::Displaystd::error::Error cho Error chúng ta tự định nghĩa:

extern crate openssl;
extern crate serde_json;

use openssl::error;
use serde_json;

enum VAPIDError {
    OpenSSL(error::ErrorStack),
    ParseJson(serder_json::error::Error),
    CustomError,
}

Implement 2 trait DisplayError

use std::fmt;
use std::error;

impl fmt::Display for VAPIDError {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
           VAPIDError::OpenSSL(ref e) => f.fmt(e),
           VAPIDError::ParseJson(ref e) => f.fmt(e),
           VAPIDError::CustomError => write!(f, "custom error"),
       }
  }
}

impl error::Error for VAPIDError {
   fn description(&self) -> &str {
      match *self {
         VAPIDError::OpenSSL(ref e) => e.description(),
         VAPIDError::ParseJson(ref e) => e.description(),
         VAPIDError::CustomError => "description custom error",
      }
   }
}

Chúng ta phải lặp đi lại quá trình trên nếu thêm 1 kind error. Nhưng có 1 crate giúp chúng ta làm những việc trên 1 cách tự động - error_chain.

Cách install error_chain như những crate khác, khai báo:

// main.rs

#[macro_use]
extern crate error_chain;

error_chain! {
  types {}
  links {}
  foregin_links {}
  errors {}
}

types {}: default error_chain sẽ tự động generate 4 types: Error, ErrorKind, ErrorExt, Result.

Error giống như enum error chúng ta khai báo ở trên sẽ chữ những ErrorKind khác nhau, ErrorExt macro define method error_chain đồi với type Result. Result là type alias:

type Result = std::result::Result<T, Error>;

Not: Error trong type alias Result là của error_chain không phải std::error::Error

links {}: Link 2 ErrorKind của 2 error_chain khác nhau.

foregin_links *: Links error kind với những std khác như openssl, hoặc serde_json
*
errors {}
:: Chúng ta sẽ tự define những error kind của chúng ta ở đây, lưu ý: method casue không được support ở đây.

Giờ sẽ convert error sang error_chain đối với ví dụ trên:

// main.rs
#[macro_use]
extern crate error_chain;

extern crate openssl;
extern crate serde_json;

use serder_json;
use openssl::error;

error_chain!  {
    types {
       Error, ErrorKind, ErrorExt, Result 
   }
   foreign_links {
      OpenSSL(error::Error),
      ParseJson(serder_json::error::Error),
   }

  errors {
     CustomError {
       description("custom error")
       display("humanable error")
     }
  }
}

fn test() -> Result<()> {
   Err(ErrorKind::CustomError.into())
}

fn main() {
   match test() {
     Err(e) => println!("descripton: {}", e.description()),
     _ => {}
   }
}
// output: custom error

Kết luận: Chúng ta đã rút ngắn hàm trăm dòng code bằng error_chain. Khi lib càng lớn việc dùng error_chain càng lợi.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Giang Nguyen

20 bài viết.
34 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
30 5
(Ảnh) Hai ngày nay mình đã tìm hiểu về Amazon S3, Cloudfront và Letsencrypt để xây dựng 2 trang web static, thứ nhất là trang chủ của (Link) và t...
Giang Nguyen viết 1 năm trước
30 5
White
9 0
Đôi dòng về ID3 (Ảnh) Nếu bạn nào chưa biết thì có thể đọc phần này, hoặc biết rồi thì có thể next tới phần kế tiếp nhé. 1. Giới thiệu Như hì...
Giang Nguyen viết 12 tháng trước
9 0
White
8 0
Type Result Type trên dùng để làm gì? Result được dùng cho những trường hợp chúng ta muốn return lại một giá trị nào đó (Ok) hoặc propagating erro...
Giang Nguyen viết 11 tháng trước
8 0
Bài viết liên quan
White
18 1
Toán tử XOR có tính chất: + A XOR A = 0 + 0 XOR A = A Với tính chất này, có thể cài đặt bài toán sau với độ phức tạp O(N) về runtime, và với O(1)...
kiennt viết hơn 1 năm trước
18 1
White
3 3
Hôm nay tự viết lại cái note này về quá trình học Rust, xem như là tự giúp mình nhớ sâu và rõ hơn về Rust. Note này sẽ ngắn gọn hơn bản (Link). Sơ...
Giang Nguyen viết 1 năm trước
3 3
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
20 bài viết.
34 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!