Goroutine'lerde Panic'i Yakalamak: Graceful Error Handling
Go'da goroutine'ler eşzamanlı işleri yönetmenin temel yolu olsa da, içinde panic oluşursa tüm program çöker. Ana goroutine'de recover yapsan bile, arkaplanda çalışan diğer goroutine'lerdeki panic'i yakalayamazsın.
Sorun şu: bir goroutine'de panic olursa, o goroutine'yi başlatan kod bunu bilmez ve program beklenmedik şekilde kapanır. Bunu önlemek için her goroutine'nin içinde defer ve recover kullanman gerekir.
Asıl çözüm, goroutine başlatmadan önce panic'i yakalayacak bir wrapper fonksiyon yazmanıdır.
1package main23import (4"fmt"5"sync"6)78func safeGo(wg *sync.WaitGroup, fn func()) {9wg.Add(1)10go func() {11defer wg.Done()12defer func() {13if r:= recover(); r!= nil {14fmt.Println("Hata yakalandı:", r)15}16}()17fn()18}()19}2021func main() {22var wg sync.WaitGroup2324safeGo(&wg, func() {25fmt.Println("Goroutine 1 çalışıyor")26})2728safeGo(&wg, func() {29panic("Goroutine 2'de sorun!")30})3132safeGo(&wg, func() {33fmt.Println("Goroutine 3 çalışıyor")34})3536wg.Wait()37fmt.Println("Program başarıyla kapandı")38}Çıktı:
1Goroutine 1 çalışıyor2Goroutine 3 çalışıyor3Hata yakalandı: Goroutine 2'de sorun!4Program başarıyla kapandıBurada safeGo fonksiyonu, her goroutine'yi defer ve recover ile sarmalıyor. Panic oluşursa yakalanır ve program çökmez. sync.WaitGroup tüm goroutine'lerin bitmesini bekler.
Bir adım öteye gitmek istersen, hataları bir kanal üzerinden ana goroutine'ye gönderebilirsin. Böylece hangi goroutine'de ne hatası olduğunu takip edebilirsin.
1func safeGoWithError(wg *sync.WaitGroup, errChan chan error, fn func()) {2wg.Add(1)3go func() {4defer wg.Done()5defer func() {6if r:= recover(); r!= nil {7errChan <- fmt.Errorf("panic: %v", r)8}9}()10fn()11}()12}Sık yapılan hata: defer recover'ı doğrudan goroutine'nin başına koymak ama panik yığını izini kaybetmek. Hata mesajını loglaman gerekir, yoksa neyin patladığını anlamak zor olur.
0 yorum