CodeBlanks Logo Icon CodeBlanks

Hata yönetimi

anyhow ile API hatalarını yönetirsin.

Hata yönetimi

Kullanıcının hatalı kaydı düzeltebilmesi için hatanın nerede ve neden olduğunu bilmesi gerekir. Gerçek projede anyhow::Context ile eklenen bağlamı burada bir hata enum'ı ile kuruyoruz:

#[derive(Debug)]
enum KayitHatasi {
    AlanSayisi { no: usize, adet: usize },
    Id { no: usize, deger: String },
}

impl fmt::Display for KayitHatasi {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            KayitHatasi::AlanSayisi { no, adet } => write!(f, "kayıt {no}: 5 alan beklendi, {adet} geldi"),
            KayitHatasi::Id { no, deger } => write!(f, "kayıt {no}: geçersiz id: {deger}"),
        }
    }
}

Hatayla dönen okuyucu

Bu kez bozuk kaydı atlamak yerine ilk hatada duruyoruz; collect ile Result<Vec<_>, _> toplamak bunu tek satırda yapar:

fn oku(veri: &str) -> Result<Vec<Yazi>, KayitHatasi> {
    veri.lines()
        .enumerate()
        .map(|(i, s)| kayit_coz(i + 1, s))
        .collect()
}

Uygulama Hatalı kaydı raporla

Yukarıdaki KayitHatasi (Display ile), kayit_coz(no, s) ve oku fonksiyonlarını yaz. İki geçerli kayıt için N yazı, x|a|b|c|true için hatayı yazdır.

Başlangıç kodu

main.rs
#[derive(Debug, Clone)]
struct Yazi {
    id: u32,
    konu: String,
    yazar: String,
    etiketler: Vec<String>,
    yayinda: bool,
}

fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
use std::fmt;

#[derive(Debug, Clone)]
struct Yazi {
    id: u32,
    konu: String,
    yazar: String,
    etiketler: Vec<String>,
    yayinda: bool,
}

#[derive(Debug)]
enum KayitHatasi {
    AlanSayisi { no: usize, adet: usize },
    Id { no: usize, deger: String },
}

impl fmt::Display for KayitHatasi {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            KayitHatasi::AlanSayisi { no, adet } => write!(f, "kayıt {no}: 5 alan beklendi, {adet} geldi"),
            KayitHatasi::Id { no, deger } => write!(f, "kayıt {no}: geçersiz id: {deger}"),
        }
    }
}

fn kayit_coz(no: usize, s: &str) -> Result<Yazi, KayitHatasi> {
    let alanlar: Vec<&str> = s.split('|').collect();
    let [id, konu, yazar, etiket, yayinda] = alanlar[..] else {
        return Err(KayitHatasi::AlanSayisi { no, adet: alanlar.len() });
    };
    Ok(Yazi {
        id: id.parse().map_err(|_| KayitHatasi::Id { no, deger: id.to_string() })?,
        konu: konu.to_string(),
        yazar: yazar.to_string(),
        etiketler: etiket.split(',').map(String::from).collect(),
        yayinda: yayinda == "true",
    })
}

fn oku(veri: &str) -> Result<Vec<Yazi>, KayitHatasi> {
    veri.lines().enumerate().map(|(i, s)| kayit_coz(i + 1, s)).collect()
}

fn main() {
    match oku("1|Rust ile başlangıç|ece|rust|true\n2|Sahiplik|can|rust|false") {
        Ok(v) => println!("{} yazı", v.len()),
        Err(e) => println!("{}", e),
    }
    match oku("x|a|b|c|true") {
        Ok(v) => println!("{} yazı", v.len()),
        Err(e) => println!("{}", e),
    }
}

Beklenen çıktı

2 yazı
kayıt 1: geçersiz id: x

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Kayıt numarasını hataya eklemek için en uygun yer neresi?

  • Display uygulamasında
  • Hiçbir yerde
  • Satırları enumerate ile dolaşan okuma döngüsünde Doğru cevap
  • main içinde

Açıklama: Numarayı yalnızca döngü bilir; bu yüzden hatayı oluşturan fonksiyona numara parametre olarak verilir.

2 Numaralı dolaşma

Soru
veri.lines()
    .____()
    .map(|(i, s)| kayit_coz(i + 1, s))
    .collect()
Cevap
veri.lines()
    .enumerate()
    .map(|(i, s)| kayit_coz(i + 1, s))
    .collect()

Açıklama: enumerate her satıra sırasını ekler; hatada kullanılır.

3 Kayıt ve hata

Kavram Anlamı
x|a|b|c|true geçersiz id: x
1|a|b 5 alan beklendi, 3 geldi
(geçerli) Ok
İlk hata Okuma durur

Orta seviye bölümündeki tüm dersler