Darsliklar Go Lang Xatolarni boshqarish

Go Lang Go Lang Xatolarni boshqarish

Xatolarni boshqarish — Go’ning boshqa ko’p tillardan tubdan farq qiladigan jihati. Go’da try/catch yo’q — xato oddiy qiymat sifatida, funksiyaning oxirgi qaytish natijasi qilib, ochiq-oydin qaytariladi.

errorGo’ning o’rnatilgan interfeysi: type error interface { Error() string }. Har qanday tur, agar Error() string metodiga ega bo’lsa, error bo’la oladi. Funksiya xato qaytarganda, chaqiruvchi uni albatta tekshirishi kutiladi.

error qaytarish va tekshirish

Funksiya qiymat bilan birga error ham qaytaradi — muvaffaqiyatli bo’lsa, xato o’rniga nil qaytadi:

package main

import "fmt"

func yosh(qiymat int) error {
    if qiymat < 0 {
        return fmt.Errorf("noto'g'ri yosh: %d manfiy bo'lishi mumkin emas", qiymat)
    }
    return nil
}

func main() {
    err := yosh(-5)
    if err != nil {
        fmt.Println("Xato:", err)
    }

    err2 := yosh(25)
    if err2 == nil {
        fmt.Println("Xato yo'q")
    }
}
Xato: noto'g'ri yosh: -5 manfiy bo'lishi mumkin emas
Xato yo'q

fmt.Errorffmt.Sprintf kabi formatlaydi, lekin string o’rniga error qaytaradi. if err != nil — Go kodida eng ko’p uchraydigan qatorlardan biri; deyarli har bir funksiya chaqiruvidan keyin xato shu tarzda tekshiriladi.

O’z xato turingizni yaratish

Oddiy matndan ko’proq ma’lumot (masalan, aniq raqamlar) kerak bo’lsa, Error() string metodiga ega maxsus struct yaratiladi:

package main

import "fmt"

type BalansXatosi struct {
    Kerak, Mavjud int
}

func (b *BalansXatosi) Error() string {
    return fmt.Sprintf("balans yetarli emas: kerak %d, mavjud %d", b.Kerak, b.Mavjud)
}

func yech(balans, summa int) (int, error) {
    if summa > balans {
        return 0, &BalansXatosi{Kerak: summa, Mavjud: balans}
    }
    return balans - summa, nil
}

func main() {
    _, err := yech(1000, 5000)
    if err != nil {
        fmt.Println(err)
    }
}
balans yetarli emas: kerak 5000, mavjud 1000

*BalansXatosiError() string metodiga ega bo’lgani uchun error interfeysini avtomatik qanoatlantiradi (interfeys darsida ko’rgan yashirin qanoatlantirish). fmt.Println(err) chaqirilganda Go avtomatik err.Error()ni chaqiradi.

Xatoni “o’rash” (wrapping) va errors.Is

Katta dasturlarda xato bir necha qatlam funksiya orqali o’tadi. %w verbi orqali asl xatoni yo’qotmasdan, unga kontekst qo’shish mumkin:

package main

import (
    "errors"
    "fmt"
)

var ErrTopilmadi = errors.New("topilmadi")

func qidir(id int) error {
    if id != 1 {
        return fmt.Errorf("id %d qidirishda xato: %w", id, ErrTopilmadi)
    }
    return nil
}

func main() {
    err := qidir(5)
    fmt.Println(err)
    fmt.Println(errors.Is(err, ErrTopilmadi))
}
id 5 qidirishda xato: topilmadi
true

%wErrTopilmadini yangi xato ichiga “o’radi”, xabar esa kengaydi. errors.Is(err, ErrTopilmadi) — tashqi xabar boshqacha bo’lsa ham, ichida aynan ErrTopilmadi “o’ralganini” true deb topa oladi. Bu, ayniqsa, “bu xato aynan shu turdanmi?” degan savolga chuqur qatlamlar ortidan ham to’g’ri javob berish uchun kerak.

Nega panic emas, error

Go’da oddiy, kutilgan xato holatlari (fayl topilmadi, noto’g’ri kiritish) uchun har doim error ishlatiladi — panic esa faqat dasturchi xatosi yoki chindan tiklab bo’lmaydigan holat uchun saqlanadi:

Yondashuv Qachon ishlatiladi
error qaytarish kutilgan, oddiy xato holatlari (fayl yo’q, noto’g’ri ma’lumot)
panic dasturchi xatosi, tiklab bo’lmaydigan holat (nil ko’rsatkich, massiv chegarasidan chiqish)

Keyingi darsda aynan panic va uni recover bilan tutib olishni ko’ramiz.