Darsliklar Go Lang Panic va Recover

Go Lang Go Lang Panic va Recover

Panic va Recover — Go’ning favqulodda holatlarni boshqarish mexanizmi, oldingi darsda ko’rgan errordan farqli, kutilmagan, jiddiy vaziyatlar uchun mo’ljallangan. panic dastur ijrosini darhol to’xtatadi, recover esa uni tutib, dasturni qulashdan saqlab qoladi.

panic / recoverpanic(qiymat) — joriy funksiyani darhol to’xtatib, chaqiruvchilar zanjiri bo’ylab yuqoriga “otiladi”. recover() — faqat defer bilan chaqirilgan funksiya ichida ishlaydi va otilayotgan panic’ni “ushlab qoladi”.

panic — dasturni to’xtatish

panic chaqirilgan zahoti, joriy funksiyaning qolgan qismi bajarilmaydi:

package main

import "fmt"

func main() {
    fmt.Println("boshlash")
    panic("xato")
}
boshlash
panic: xato

goroutine 1 [running]:
main.main()
    ...
exit status 2

panic("xato")dan keyingi hech qanday kod ishlamaydi — dastur to’xtaydi va stack trace bilan chiqib ketadi. recover bo’lmasa, panic butun dasturni qulatadi.

recover — panic’ni tutib olish

recover() faqat defer ichida chaqirilganda ma’noga ega — u panic’ni “ushlab”, dastur ijrosini normal davom ettirishga imkon beradi:

package main

import "fmt"

func xavfsizBajar() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Tiklandi:", r)
        }
    }()

    fmt.Println("Boshlash")
    panic("kutilmagan xato")
}

func main() {
    xavfsizBajar()
    fmt.Println("Dastur davom etmoqda")
}
Boshlash
Tiklandi: kutilmagan xato
Dastur davom etmoqda

defer func() { ... }() — anonim funksiya defer qilindi, u xavfsizBajar tugashidan oldin, panic yuz berganda ham ishlaydi. recover() panic qiymatini ("kutilmagan xato") qaytardi, va eng muhimi — main ichidagi "Dastur davom etmoqda" baribir chop etildi. xavfsizBajar()ning o’zi to’xtagan bo’lsa-da, dastur butunlay qulamadi.

Panic chaqiruvlar zanjiri bo’ylab tarqaladi

Agar recover bo’lmasa, panic har bir qatlamdagi deferlarni ishga tushirib, chaqiruvchiga yuqoriga tarqalaveradi:

package main

import "fmt"

func ichki() {
    panic("ichkarida muammo")
}

func tashqi() {
    defer fmt.Println("tashqi tozalandi")
    ichki()
}

func main() {
    defer fmt.Println("main tozalandi")
    tashqi()
    fmt.Println("bu qator ishlamaydi")
}
tashqi tozalandi
main tozalandi
panic: ichkarida muammo

goroutine 1 [running]:
main.ichki(...)
    ...
main.tashqi()
    ...
main.main()
    ...
exit status 2

E’tibor bering: "bu qator ishlamaydi" chindan ham chop etilmadi — panic tashqi()ni ham, keyin main()ni ham to’xtatdi. Lekin ikkala funksiyaning deferlari ("tashqi tozalandi", "main tozalandi") baribir, panic tarqalish jarayonida, ishga tushdi. Stack trace esa panic qaysi funksiyalar zanjiri orqali o’tganini (ichkitashqimain) aniq ko’rsatadi.

Qachon panic ishlatish kerak

Amaliy qoida: panicni faqat dasturchi xatosi yoki chindan “davom etib bo’lmaydigan” holatlar uchun ishlating — foydalanuvchi kiritgan noto’g’ri ma’lumot, tarmoq xatosi kabi kutilgan holatlar uchun har doim oldingi darsdagi error ishlatiladi. Standart kutubxonaning o’zi ham shu qoidaga amal qiladi: masalan, massiv chegarasidan chiqish avtomatik panic beradi, chunki bu — tuzatib bo’lmaydigan dasturchi xatosi.