برنامه نویسی

دست زدن به خطای زنگ در مقایسه: به هر حال در مقابل Thiserror vs Snafu

پوشش

رسیدگی به خطا بخش مهمی از توسعه زنگ زدگی است. زنگ زدگی Result پشتیبانی اساسی را ارائه می دهد ، اما اجرای خاص بسته به سناریو متفاوت است. این مقاله سه ابزار استفاده از خطای متداول را معرفی می کند –anyhowبا thiserrorوت snafu– بیان ویژگی های آنها و سناریوهای قابل اجرا ، و به شما کمک می کند تا از طریق نمونه های عملی نحوه استفاده از آنها در پروژه ها را درک کنید. این که آیا شما در حال تهیه برنامه ها هستید یا کتابخانه را در حال نوشتن هستید ، این مقاله می تواند به عنوان یک مرجع ارزشمند باشد.

این مقاله عمیقاً به سه ابزار اصلی برای رسیدگی به خطای زنگ زدگی می پردازد:

  • anyhow مناسب برای رسیدگی به خطای سریع و یکپارچه ، ایده آل برای توسعه برنامه است.
  • thiserror از انواع خطای سفارشی پشتیبانی می کند ، و آن را برای توسعه کتابخانه مناسب می کند.
  • snafu مدیریت خطای محور زمینه را فراهم می کند ، مناسب برای سیستم های پیچیده.

با مقایسه نقاط قوت و ضعف آنها و نشان دادن نمونه های واقعی کد ، ما به شما نشان خواهیم داد که چگونه می توانید ابزار مناسب را بر اساس نیازهای پروژه انتخاب کنید. ما همچنین مراحل تنظیم پروژه و کد مثال را ارائه می دهیم تا به شما در رسیدگی به خطاها به طور مؤثرتر در زنگ زدگی کمک کنیم.

رسیدگی به خطای زنگ زدگی

رسیدگی به خطا: anyhowبا thiserrorبا snafu

  • anyhow: رسیدگی به خطای یکپارچه و ساده ، مناسب برای برنامه نویسی در سطح برنامه
  • thiserror: رسیدگی به خطای سفارشی و غنی ، مناسب برای برنامه نویسی در سطح کتابخانه
  • snafu: مدیریت خطای ریز ریز

توجه: هنگام توسعه ، به اندازه توجه کنید Resultبشر

anyhow خطا: رسیدگی به خطای سطح برنامه

تبدیل و رسیدگی به خطای متحد با anyhow::Error:

  • یک متحد فراهم می کند anyhow::Error تایپ کنید ، پشتیبانی از هر نوع خطایی که پیاده سازی کنید std::error::Error
  • استفاده می کند ? اپراتور برای انتشار خطای خودکار ، ساده کردن خطای چند لایه تو در تو
  • پشتیبانی از افزودن زمینه پویا (از طریق context() روش) برای تقویت خوانایی خطا
fn get_cluster_info() -> Result<ClusterMap, anyhow::Error> {  // Error 3: Err3
  let config = std::fs::read_to_string("cluster.json")?;    // Error 1: Err1
  // let config = std::fs::read_to_string("cluster.json").context("...")?;    // Error 1: Err1
  let map: ClusterMap = serde_json::from_str(&config)?;     // Error 2: Err2
  Ok(map)
}

struct Err1 {...}
struct Err2 {...}

match ret {
  Ok(v) => v,
  Err(e) => return Err(e.into())
}

Err1 => Err3: impl From<Err1> for Err3
Err2 => Err3: impl From<Err2> for Err3

impl From<Err1> for Err3 {
  fn from(v: Err1) -> Err3 {
    ...
  }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

thiserror خطا: تعریف خطاهای سطح کتابخانه

  • به طور خودکار انواع خطایی ایجاد می کند که مطابق با std::error::Error از طریق ماکرو
  • از منابع خطای تو در تو پشتیبانی می کند (با استفاده از #[from] ویژگی) و اطلاعات خطای ساختاری
  • اجازه می دهد تا سفارشی سازی الگوهای پیام خطا (به عنوان مثال ، #[error("Invalid header: {expected}")])

مرجع: Rust Std :: خطا :: خطای مستندات صفت

از آنجا که Error صفت نیاز به اجرای هر دو دارد Debug وت Display:

pub trait Error: Debug + Display {
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

می توان مانند این چاپ کرد:

Error -> println!("{}/ {:?}", err)
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

snafu خطا: مدیریت خطای محور متن

  • خطاهای زیرین را به خطاهای خاص دامنه تبدیل می کند Snafu کلان
  • از اتصال متن ساختار یافته (مانند مسیرهای فایل ، پارامترهای ورودی) در زنجیره خطا پشتیبانی می کند
  • فراهم می کند ensure! ماکرو برای ساده کردن بررسی شرایط و پرتاب خطا

thiserror در مقابل snafu

برای اطلاعات بیشتر ، به: KUBE-RS/KUBE بحث #453 مراجعه کنید

راهنمای مقایسه و انتخاب

بعد به هر حال اینرا خندق
نوع خطا نوع پویا متحد نوع سفارشی استاتیک نوع دامنه محور
پشتیبانی متن رشته پویا زمینه های ساختاری زمینه های ساختاری + الگوهای پویا
مرحله مناسب توسعه برنامه (تکرار سریع) توسعه کتابخانه (رابط های پایدار) سیستم های پیچیده (قابلیت حفظ)
منحنی یادگیری کم (بدون نیاز به پیش بینی انواع) متوسط ​​(نیاز به طراحی ساختارهای خطا دارد) بالا (نیاز به درک مدل های زمینه)
کاربران معمولی توسعه دهندگان / توسعه دهندگان ابزار برنامه نویسی Frontend توسعه دهندگان چارچوب مهندسان زیرساخت

اجرای عملی

ایجاد و اولیه سازی پروژه rust-ecosystem-learning بر اساس یک الگوی

cargo generate --git git@github.com:qiaopengjun5162/rust-template.git
cd rust-ecosystem-learning
code .
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

ساختار دایرکتوری پروژه

rust-ecosystem-learning on  main [!] is 📦 0.1.0 via 🦀 1.85.0 via 🅒 base
➜ tree . -L 6 -I 'target|coverage|coverage_report|node_modules'

.
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── README.md
├── _typos.toml
├── cliff.toml
├── deny.toml
├── docs
└── src
    ├── error.rs
    ├── lib.rs
    └── main.rs

3 directories, 12 files
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

وابستگی ها را اضافه کنید

cargo add anyhow
cargo add thiserror
cargo add serde_json
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

main.rs پرونده

use anyhow::Context;
use rust_ecosystem_learning::MyError;
use std::fs;
use std::mem::size_of;

fn main() -> Result<(), anyhow::Error> {
    println!("size of anyhow::Error: {}", size_of::<anyhow::Error>());
    println!("size of std::io::Error: {}", size_of::<std::io::Error>());
    println!(
        "size of std::num::ParseIntError: {}",
        size_of::<std::num::ParseIntError>()
    );
    println!(
        "size of serde_json::Error: {}",
        size_of::<serde_json::Error>()
    );
    println!("size of string: {}", size_of::<String>());
    println!("size of MyError: {}", size_of::<MyError>());

    let filename = "non_existent_file.txt";
    let _fd =
        fs::File::open(filename).with_context(|| format!("Cannot find file: {}", filename))?;

    fail_with_error()?;
    Ok(())
}

fn fail_with_error() -> Result<(), MyError> {
    Err(MyError::Custom("This is a custom error".to_string()))
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

lib.rs پرونده

mod error;

pub use error::MyError;
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

error.rs پرونده

use thiserror::Error;

#[derive(Error, Debug)]
pub enum MyError {
    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),

    #[error("Parse error: {0}")]
    Parse(#[from] std::num::ParseIntError),

    #[error("Serialize JSON error: {0}")]
    Serialize(#[from] serde_json::Error),

    // #[error("Error: {a}, {b:?}, {c:?}, {d:?}")]
    // BigError {
    //     a: String,
    //     b: Vec,
    //     c: [u8; 64],
    //     d: u64,
    // },

    #[error("Error: {0:?}")]
    BigError(Box<BigError>),

    #[error("An error occurred: {0}")]
    Custom(String),
}

#[derive(Debug)]
pub struct BigError {
    pub a: String,
    pub b: Vec<String>,
    pub c: [u8; 64],
    pub d: u64,
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

Cargo.toml پرونده

[package]
name = "rust-ecosystem-learning"
version = "0.1.0"
edition = "2021"
license = "MIT"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1.0.97"
serde = { version = "1.0.217", features = ["derive"] }
serde_json = "1.0.140"
thiserror = "2.0.11"
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

اجرای پروژه

rust-ecosystem-learning on  main [!] is 📦 0.1.0 via 🦀 1.85.0 via 🅒 base took 2.9s
➜ cargo run
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/rust-ecosystem-learning`
size of anyhow::Error: 8
size of std::io::Error: 8
size of std::num::ParseIntError: 1
size of serde_json::Error: 8
size of string: 24
size of MyError: 24
Error: Cannot find file: non_existent_file.txt

Caused by:
    No such file or directory (os error 2)
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

خلاصه

ابزارهای دست زدن به خطای زنگ هرکدام تمرکز خاص خود را دارند:

  • anyhow ساده و کارآمد است ، مناسب برای توسعه برنامه.
  • thiserror ساختاری و واضح است ، برای طراحی کتابخانه مناسب است.
  • snafu زمینه غنی را ارائه می دهد و آن را برای سناریوهای پیچیده ایده آل می کند.

از طریق تجزیه و تحلیل و نمونه های عملی در این مقاله ، می توانید بر اساس نیازهای واقعی خود ، راه حل مناسب برای رسیدگی به خطای مناسب را انتخاب کنید.

رسیدگی به خطای مناسب باعث می شود کد شما قوی تر شود – آن را تمرین کنید و کیفیت پروژه های زنگ زدگی خود را بالا ببرید!


ما Leapcell ، انتخاب برتر شما برای میزبانی پروژه های زنگ زدگی هستیم.

جهش

Leapcell بستر سرور نسل بعدی برای میزبانی وب ، کارهای ASYNC و REDIS است:

پشتیبانی چند زبانی

  • با node.js ، پایتون ، برو یا زنگ زدگی توسعه دهید.

پروژه های نامحدود را به صورت رایگان مستقر کنید

  • فقط برای استفاده پرداخت کنید – بدون درخواست ، بدون هزینه.

راندمان هزینه بی نظیر

  • پرداخت به عنوان شما بدون هیچ گونه هزینه بیکار.
  • مثال: 25 دلار از درخواست های 6.94M در زمان پاسخ متوسط ​​60ms پشتیبانی می کند.

تجربه توسعه دهنده ساده

  • UI بصری برای راه اندازی بی دردسر.
  • خطوط لوله CI/CD کاملاً خودکار و ادغام GITOPS.
  • معیارهای زمان واقعی و ورود به سیستم برای بینش های عملی.

مقیاس پذیری بی دردسر و عملکرد بالا

  • مقیاس خودکار برای رسیدگی به همزمانی بالا با سهولت.
  • صفر سربار عملیاتی – فقط روی ساختمان تمرکز کنید.

در اسناد بیشتر کاوش کنید!

Leapcell را امتحان کنید

ما را در X دنبال کنید: LeapCellHQ


در وبلاگ ما بخوانید

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا