首页 >后端开发 >Golang >如何优雅地终止 Go 中的 Goroutines 并处理错误?

如何优雅地终止 Go 中的 Goroutines 并处理错误?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-11-12 07:21:02957浏览

How to Gracefully Terminate Goroutines and Handle Errors in Go?

惯用的 Goroutine 终止和错误处理:案例研究

在 Go 中,处理 Goroutine 终止对于开发人员来说通常是一个挑战。一个常见的问题是确保发生错误时正确清理 goroutine。本文演示了使用错误分组来解决此问题的优雅且惯用的解决方案。

考虑以下示例:

package main

import (
        "sync"
        "time"
)

func fetchAll() error {
        wg := sync.WaitGroup{}
        errs := make(chan error)

        // run all the http requests in parallel
        for i := 0; i < 4; i++ {
                wg.Add(1)
                go func(i int) {
                        defer wg.Done()

                        // pretend this does an http request and returns an error
                        time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
                        errs <- fmt.Errorf("goroutine %d's error returned", i)
                }(i)
        }

        // wait until all the fetches are done and close the error
        // channel so the loop below terminates
        go func() {
                wg.Wait()
                close(errs)
        }()

        // return the first error
        for err := range errs {
                if err != nil {
                        return err
                }
        }

        return nil
}

此实现有一个严重缺陷:它泄漏了 goroutine。修复方法是使用错误组:

package main

import (
        "context"
        "fmt"
        "math/rand"
        "time"

        "golang.org/x/sync/errgroup"
)

func fetchAll(ctx context.Context) error {
        errs, ctx := errgroup.WithContext(ctx)

        // run all the http requests in parallel
        for i := 0; i < 4; i++ {
                errs.Go(func() error {
                        // pretend this does an http request and returns an error                                                  
                        time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)                                               
                        return fmt.Errorf("error in go routine, bailing")                                                      
                })
        }

        // Wait for completion and return the first error (if any)                                                                 
        return errs.Wait()
}

错误组会自动等待所有 goroutine 成功完成,或者在发生错误时取消剩余的 goroutine。在上述情况下,遇到错误的第一个 goroutine 会触发所有其他 goroutine 的取消,并将错误传播回调用者。当周围的上下文被取消时,上下文的使用确保了优雅的终止。

以上是如何优雅地终止 Go 中的 Goroutines 并处理错误?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn