美文网首页
errgroup改造

errgroup改造

作者: 彳亍口巴 | 来源:发表于2022-09-30 11:36 被阅读0次
g := &errgroup.Group{}
    g.Go(func() error {
        return nil
    })
    g.Go(func() error {
        return nil
    })
    if err:=g.Wait();err!=nil {
        panic(err)
    }

在需要开启协程并发请求的时候,通常可以通过errgroup包封装的Group进行调用,不用再去关注Add多少个协程和什么时候Done,在每个Go方法中已经封装好一对一了

func (g *Group) Go(f func() error) {
    g.wg.Add(1)

    go func() {
        defer g.wg.Done()

        if err := f(); err != nil {
            g.errOnce.Do(func() {
                g.err = err
                if g.cancel != nil {
                    g.cancel()
                }
            })
        }
    }()
}

调用Go方法后再调用Wait方法等待协程运行结束即可。

func (g *Group) Wait() error {
    g.wg.Wait()
    if g.cancel != nil {
        g.cancel()
    }
    return g.err
}

但是上面的Wait方法只给我们返回了错误,具体是哪个Go方法里面出现错误,我们只能通过日志打印出来才知道,并且模调判断服务调用属于哪种错误是根据返回码来的,这时候我们可以改造一下Group,让它给我们同时返回错误码和错误

package main

import (
    "fmt"
    "sync"
)

// Group 结构体
type Group struct {
    wg      sync.WaitGroup
    errOnce sync.Once
    ret     int32
    err     error
}

// Wait wait
func (obj *Group) Wait() (int32, error) {
    obj.wg.Wait()
    if obj.ret != 0 || obj.err != nil {
        return obj.ret, obj.err
    }
    return 0, nil
}

// Go 执行方法
func (obj *Group) Go(f func() (int32, error)) {
    obj.wg.Add(1)
    go func() {
        defer obj.wg.Done()
        ret, err := f()
        if err != nil || ret != 0 {
            obj.errOnce.Do(func() {
                obj.err = err
                obj.ret = ret
            })
        }
    }()
}

func main() {
    test01()
}

func test01() {
    g := &Group{}
    g.Go(func() (int32, error) {
        fmt.Println("g1")
        return 0, nil
    })
    g.Go(func() (int32, error) {
        fmt.Println("g2")
        return 2, nil
    })
    g.Go(func() (int32, error) {
        fmt.Println("g3")
        return 3, fmt.Errorf("g3 err")
    })
    if ret, err := g.Wait(); ret != 0 || err != nil {
        fmt.Printf("ret:%d err:%+v", ret, err)
        return
    }
    fmt.Println("没有错误")
}

对于错误码的处理,和错误一样,都是通过Once只处理一次,不会覆盖

相关文章

网友评论

      本文标题:errgroup改造

      本文链接:https://www.haomeiwen.com/subject/jiblartx.html