Millist lähenemisviisi kasutatakse Go-s gorutinides tekkivate vigade töötlemiseks?
sobes.tech AI
Vastus AI-lt
Go-s räägime vigade töötlemisest gorutinates, kasutades tavaliselt järgmisi lähenemisviise:
-
Vigade edastamine kanalite kaudu: Loome kanali vigade edastamiseks põhivoogule või teisele gorutinale, mis saab neid töödelda:
// Näide vea edastamisest kanalite kaudu func worker(id int, errors chan<- error) { // ... töö tegemine if somethingWentWrong { errors <- fmt.Errorf("viga gorutinas %d", id) return } // ... edukas lõpetamine } func main() { errorCh := make(chan error, nWorkers) // Buferiseeritud kanal for i := 0; i < nWorkers; i++ { go worker(i, errorCh) } for i := 0; i < nWorkers; i++ { err := <-errorCh if err != nil { log.Printf("avastatud viga: %v", err) // Vigade töötlemine } } } -
sync.WaitGroupja vea kanalite kasutamine:sync.WaitGroupaitab oodata kõigi gorutinate lõpetamist, samas kui kanal kogub vigu:// Näide WaitGroup ja vea kanaliga func workerWithWG(id int, wg *sync.WaitGroup, errors chan<- error) { defer wg.Done() // ... töö tegemine if somethingWentWrong { errors <- fmt.Errorf("viga gorutinas %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) // Oluline on kanal sulgeda pärast WaitGroup-i for err := range errorCh { log.Printf("avastatud viga: %v", err) // Vigade töötlemine } } -
Väärtuse ja vea tagastamine funktsioonist, mis käivitatakse gorutinana: Kui gorutina täidab konkreetset ülesannet ja saab tagastada tulemuse ja/või vea, saab selle funktsiooni sisse pakkida:
// Näide väärtuse ja vea tagastamisest type result struct { value int err error } func doSomething(id int) (int, error) { // ... töö tegemine if somethingWentWrong { return 0, fmt.Errorf("viga gorutinas %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("avastatud viga: %v", res.err) // Vigade töötlemine } else { log.Printf("tulemus: %d", res.value) } } } -
Konteksti (
context.Context) kasutamine tühistamiseks ja vigade töötlemiseks: Konteksti saab kasutada gorutinate tühistamise signaalimiseks või vea edastamiseks allapoole hierarhias:// Näide kontekstiga func workerWithContext(ctx context.Context, id int, errors chan<- error) { select { case <-ctx.Done(): errors <- fmt.Errorf("gorutina %d tühistatud: %v", id, ctx.Err()) return default: // ... töö tegemine if somethingWentWrong { errors <- fmt.Errorf("viga gorutinas %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) } // Mõne aja pärast saab kutsuda cancel() tühistamiseks // cancel() // Vigade kogumine go func() { for err := range errorCh { log.Printf("avastatud viga: %v", err) } }() // Oodata lõpetamist või muud loogikat // ... }
Valik konkreetse lähenemise vahel sõltub vigade töötlemise nõuetest ja rakenduse arhitektuurist.