为了账号安全,请及时绑定邮箱和手机立即绑定

并行获取多个字段的模式

并行获取多个字段的模式

Go
jeck猫 2023-07-17 14:48:55
我需要从外部服务为我的系统并行获取多个字段(在本例中,通过 Name()、Age() 和 CanDrive() 方法模拟)。fetchUser() 方法可以实现我想要的功能,但它似乎太冗长了,特别是如果您认为我可以有 10 个以上的字段。我有更好的方法可以实现这一点吗?游乐场:https://play.golang.org/p/90sNq1GmrD8代码(与游乐场中相同):package mainimport (    "fmt"    "sync")type User struct {    Name string    Age int    CanDrive *bool}func Name() (string, error) {    return "foobar", nil}func Age() (int, error) {    return 25, nil}func CanDrive() (bool, error) {    return true, nil}func fetchUser() (*User, error) {    var wg sync.WaitGroup    errs := make(chan error)    user := &User{}    wg.Add(1)    go func() {        var err error        defer wg.Done()        user.Name, err = Name()        errs <- err    }()    wg.Add(1)    go func() {        var err error        defer wg.Done()        user.Age, err = Age()        errs <- err    }()    wg.Add(1)    go func() {        defer wg.Done()        canDrive, err := CanDrive()        if err == nil {            user.CanDrive = &canDrive        }        errs <- err    }()    // wait until all go-routines are completed successfully    // if that's the case, close the errs channel    go func() {        wg.Wait()        close(errs)    }()    // keep waiting for errors (or for the error channel to be closed    // if all calls succeed)    for err := range errs {        if err != nil {            return nil, err        }    }    return user, nil}func main() {    user, _ := fetchUser()    fmt.Println(user)}
查看完整描述

1 回答

?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

在不了解您的场景的更多细节的情况下,我唯一的建议是将 Go 例程错误处理分离到另一个包中。

幸运的是,已经存在一个可以执行相同操作的包,名为errgroup. 以下是使用该包的原始代码的实现errgroup

package main


import (

    "context"

    "fmt"


    "golang.org/x/sync/errgroup"

)


type User struct {

    Name     string

    Age      int

    CanDrive *bool

}


func Name() (string, error) {

    return "foobar", nil

}


func Age() (int, error) {

    return 25, nil

}


func CanDrive() (bool, error) {

    return true, nil

}


func fetchUser(ctx context.Context) (*User, error) {

    group, ctx := errgroup.WithContext(ctx)


    user := &User{}

    group.Go(func() (err error) {

        user.Name, err = Name()

        return

    })

    group.Go(func() (err error) {

        user.Age, err = Age()

        return

    })

    group.Go(func() error {

        canDrive, err := CanDrive()

        if err == nil {

            user.CanDrive = &canDrive

        }

        return err

    })


    if err := group.Wait(); err != nil {

        return nil, err

    }


    return user, nil

}


func main() {

    user, err := fetchUser(context.Background())

    fmt.Println(user, err)

}


查看完整回答
反对 回复 2023-07-17
  • 1 回答
  • 0 关注
  • 84 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信