Menu
Coddy logo textTech

Panic, Defer ve Recover

Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 57 / 107.

Go, hataları döndürmeyi vurgulasa da bazı durumlar gerçekten kurtarılamaz. Bu durumlar için Go, istisnai koşulları ele almaya yönelik bir mekanizma olarak panic, defer ve recover yapılarını sunar.

panic normal yürütmeyi hemen durdurur. Kullanıcı girdisinin geçersiz olması gibi beklenen hatalar için değil, sınırların dışındaki bir dizine erişmek gibi programlama hataları için ayrılmıştır:

func MustGetConfig(key string) string {
    value, exists := config[key]
    if !exists {
        panic("missing required config: " + key)
    }
    return value
}

defer, çevreleyen işlev normal olarak veya bir panic nedeniyle döndüğünde çalıştırılmak üzere bir işlevi zamanlar. Ertelenen çağrılar ters sırada (son giren, ilk çıkar) yürütülür:

func ProcessFile() {
    fmt.Println("Opening file")
    defer fmt.Println("Closing file")
    fmt.Println("Processing...")
    // Çıktı: Opening file, Processing..., Closing file
}

recover bir panic'i yakalar ve normal yürütmeye geri döner. Yalnızca ertelenmiş bir işlevin içinde çalışır:

func SafeOperation() (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("recovered from panic: %v", r)
        }
    }()
    
    riskyOperation()
    return nil
}

Bu desen, bir panic'i normal bir hataya dönüştürerek programınızın devam etmesini sağlar. Bunu ölçülü kullanın: beklenen başarısızlık durumları için hata döndürmeyi tercih edin ve panic/recover kullanımını bozulmuş durum veya kurtarılamaz koşullar gibi gerçekten istisnai durumlarla sınırlayın.

challenge icon

Görev

Kolay

panic, defer ve recover kullanarak olağandışı durumları düzgün bir şekilde ele almayı gösteren güvenli bir bölme hesaplayıcısı oluşturalım. Hesaplayıcınız riskli işlemleri deneyecek ve panic durumlarını normal şekilde ele alınabilecek normal hatalara dönüştürecektir.

Kodunuzu iki dosyaya ayıracaksınız:

  • calculator.go: Panic kurtarma özelliğiyle bölme mantığını oluşturun.

    İki tamsayı alan ve bölen sıfırsa Divide mesajıyla panic oluşturan bir "division by zero" fonksiyonu uygulayın. Aksi takdirde bölme işleminin tamsayı sonucunu döndürmelidir.

    İki tamsayı alan ve hem bir tamsayı sonucu hem de bir hata döndüren bir SafeDivide fonksiyonu uygulayın. Bu fonksiyon şunları yapmalıdır:

    • Herhangi bir panic durumundan kurtulmak için anonim bir fonksiyonla birlikte defer kullanın
    • Bir panic kurtarılırsa, onu "calculation error: [panic message]" biçiminde bir hataya dönüştürün
    • Dahili olarak Divide fonksiyonunu çağırın
    • Başarılı olursa sonucu ve nil değerini, bir panic kurtarılmışsa sıfırı ve hatayı döndürün
  • main.go: Girdiden iki tamsayı okuyun ve hesaplamayı güvenli bir şekilde gerçekleştirmek için SafeDivide kullanın. Ayrıca doğru sırada temizlik mesajları yazdırarak defer kullanımını gösterin.

    main fonksiyonunuz şunları yapmalıdır:

    • Başlangıçta Starting calculation yazdırın
    • defer yazdırmayı planlamak için Cleanup complete kullanın
    • defer yazdırmayı planlamak için başka bir Releasing resources kullanın
    • Girdi değerleriyle SafeDivide fonksiyonunu çağırın
    • Sonuca göre Result: [value] veya Error: [error message] yazdırın

Aşağıdaki girdiler sağlanacaktır:

  • 1. satır: İlk tamsayı (bölünen)
  • 2. satır: İkinci tamsayı (bölen)

Ertelenen çağrıların ters sırada (son giren, ilk çıkar) yürütüldüğünü unutmayın; bu nedenle temizlik mesajlarınız, ertelendikleri sıranın tersi olan sırada görünmelidir.

Örneğin, 20 ve 4 verildiğinde çıktınız şu şekilde olmalıdır:

Starting calculation
Result: 5
Releasing resources
Cleanup complete

Ve 10 ile 0 verildiğinde çıktınız şu şekilde olmalıdır:

Starting calculation
Error: calculation error: division by zero
Releasing resources
Cleanup complete
GEREKLİ ÇIKTI BİÇİMİ: [Çevrilmiş içeriğiniz]

Kendin dene

package main

import (
	"fmt"
)

func main() {
	// Girdiyi oku
	var dividend, divisor int
	fmt.Scanln(&dividend)
	fmt.Scanln(&divisor)

	// Başlangıç mesajını yazdır
	fmt.Println("Starting calculation")

	// TODO: Use defer to schedule "Cleanup complete" message

	// TODO: Use defer to schedule "Releasing resources" message
	// Unutma: ertelenmiş çağrılar LIFO sırasıyla çalışır (son giren, ilk çıkar)

	// TODO: SafeDivide'ı girdi değerleriyle çağır

	// TODO: Ya "Result: [value]" ya da "Error: [error message]" yazdır
	// bir hata döndürülüp döndürülmediğine göre
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online Go derleyicisi