Hata yönetimi
- Rust kursu
- Orta seviye
- Ders 109/115
- 6 dk
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
#[derive(Debug, Clone)]
struct Yazi {
id: u32,
konu: String,
yazar: String,
etiketler: Vec<String>,
yayinda: bool,
}
fn main() {
// buraya yaz
}Örnek çözüm
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
veri.lines()
.____()
.map(|(i, s)| kayit_coz(i + 1, s))
.collect()
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 |