Go-da goroutine-lərdə baş verən səhvlərin işlənməsi üçün hansı yanaşma istifadə olunur?
sobes.tech Süni İntellekt
AI-dan cavab
Go-da, gorutinlarda səhvlərin işlənməsi üçün adətən aşağıdakı yanaşmalar istifadə olunur:
-
Xətaların kanallar vasitəsilə ötürülməsi: Xəta dəyərlərini əsas axına və ya onları işləyə biləcək başqa gorutinə ötürmək üçün kanal yaradılır.
// Kanal vasitəsilə xəta ötürülməsinin nümunəsi func worker(id int, errors chan<- error) { // ... işin yerinə yetirilməsi if somethingWentWrong { errors <- fmt.Errorf("gorutində xəta %d", id) return } // ... uğurlu tamamlanma } func main() { errorCh := make(chan error, nWorkers) // Bufferli kanal for i := 0; i < nWorkers; i++ { go worker(i, errorCh) } for i := 0; i < nWorkers; i++ { err := <-errorCh if err != nil { log.Printf("tapılan xəta: %v", err) // Xəta ilə işləmə } } } -
sync.WaitGroupvə xəta kanalı istifadə edərək:sync.WaitGroupbütün gorutininlərin tamamlanmasını gözləməyə kömək edir və kanal xətaların toplanması üçün istifadə olunur.// WaitGroup və xəta kanalı ilə nümunə func workerWithWG(id int, wg *sync.WaitGroup, errors chan<- error) { defer wg.Done() // ... işin yerinə yetirilməsi if somethingWentWrong { errors <- fmt.Errorf("gorutində xəta %d", id) } } func main() { var wg sync.WaitGroup errorCh := make(chan error, nWorkers) for i := 0; i < nWorkers; i++ { wg.Add(1) go workerWithWG(i, &wg, errorCh) } wg.Wait() close(errorCh) // `WaitGroup`-dən sonra kanalın bağlanması vacibdir for err := range errorCh { log.Printf("tapılan xəta: %v", err) // Xəta ilə işləmə } } -
Fərdi funksiyadan dəyər və xəta qaytarılması: Əgər gorutinə xüsusi bir tapşırıq yerinə yetirirsə və nəticə və ya xəta qaytara bilərsə, bu dəyərləri qaytaran funksiyaya çevrilə bilər.
// Dəyər və xəta qaytaran nümunə funksiyası type result struct { value int err error } func doSomething(id int) (int, error) { // ... işin yerinə yetirilməsi if somethingWentWrong { return 0, fmt.Errorf("gorutində xəta %d", id) } return id * 10, nil } func main() { results := make(chan result, nWorkers) for i := 0; i < nWorkers; i++ { go func(idx int) { val, err := doSomething(idx) results <- result{val, err} }(i) } for i := 0; i < nWorkers; i++ { res := <-results if res.err != nil { log.Printf("tapılan xəta: %v", res.err) // Xəta ilə işləmə } else { log.Printf("nəticə: %d", res.value) } } } -
İstifadə kontekstindən (
context.Context) ləğv və xəta işləmə üçün: Kontekst gorutinin ləğvini siqnallaşdırmaq və ya xətanı aşağıya ötürmək üçün istifadə edilə bilər.// Kontekst nümunəsi func workerWithContext(ctx context.Context, id int, errors chan<- error) { select { case <-ctx.Done(): errors <- fmt.Errorf("gorutində %d ləğv olundu: %v", id, ctx.Err()) return default: // ... işin yerinə yetirilməsi if somethingWentWrong { errors <- fmt.Errorf("gorutində xəta %d", id) } } } func main() { ctx, cancel := context.WithCancel(context.Background()) errorCh := make(chan error, nWorkers) for i := 0; i < nWorkers; i++ { go workerWithContext(ctx, i, errorCh) } // Bir nöqtədə, ləğv etmək üçün cancel() çağırıla bilər // cancel() // Xətaların toplanması go func() { for err := range errorCh { log.Printf("tapılan xəta: %v", err) } }() // Tamamlanma və ya başqa logika üçün gözləmə // ... }
Seçim konkret yanaşma tətbiqin xətaların işlənməsi tələblərinə və arxitekturasına bağlıdır.