孩子的价值打印在延迟后成为常规

我正在从我的驱动程序代码中生成 5 个工作池,并从工作池返回错误。在我的主要任务中,我有另一个 go routine(go routine A ,在那个 go routine 之上添加了注释)监听错误。但是当从我的错误通道中选取数据时,我的 defer 语句正在执行。但我仍然可以看到来自 go routine A 的日志。


func ....{

var requests []Req

        err := json.Unmarshal(Data, &requests)

        if err != nil {

            log.WithError(err).Errorf("Invalid data passed for flag type %v", proto.CreateFlagReq_SET_OF.String())

            return err

        }

        f.Manager.TaskChan = make(chan Req, 100)

        f.Manager.ErrorChan = make(chan error, 100)


        for i := 0; i < f.Manager.WorkerCount; i++ {

            f.Manager.Wg.Add(1)

           //AddToSetOfcustomers just validates before addigg to redis

            go f.Manager.Work(ctx, f.redisPool.AddToSetOfcustomers, i)

        }


        for _, request := range requests {

            f.Manager.TaskChan <- request

        }

        close(f.Manager.TaskChan)


        var errors error

        **//go routine A**

        go func() {

            for {

                select {

                case err ,ok:= <- f.Manager.ErrorChan:

                    if ok{

                        errors = multierror.Append(errors, err)

                        log.Errorf("got erro1r %v",errors)

                    }else{

                        log.Info("returning")

                        return

                    }


                }

            }

        }()

        f.Manager.Wg.Wait()


        defer log.Errorf("blhgsgh   %v %v",len(f.Manager.ErrorChan),errors)

        return errors

}


我有点怀疑 defer 被执行了,然后我的主要 go 例程完成了,然后 return 被执行了,但是我能做些什么来传播我在返回之前从 multiErrors 附加的错误?


如果我尝试使用通道同步 go routine A 和我的主要 go routine(我称之为 defer 的那个),它会变成阻塞。Help appretiated


梦里花落0921
浏览 71回答 1
1回答

千巷猫影

我已经在playground中简化了您的代码。您似乎假设f.Manager.Wg.Wait()返回时所有错误都已处理。然而,错误正在一个单独的 goroutine (&nbsp;**//go routine A**) 中处理,您不会等待它完成——事实上,因为您不关闭f.Manager.ErrorChangoroutine 永远不会完成。解决这个问题的最简单方法是等待 goroutine 退出,然后再从函数返回。下面的示例 (&nbsp;playground&nbsp;) 使用一个通道来执行此操作,但WaitGroup如果您愿意,也可以使用一个。var errors []errorerrDone := make(chan struct{})go func() {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case err, ok := <-errorChan:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ok {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; errors = append(errors, err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Printf("got error %v", errors)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Printf("returning")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; close(errDone)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}()wg.Wait()// Everything sending to errorChan is now done so we can safely close the channelclose(errorChan)<-errDone // Wait for error handling goroutine to complete请注意,defer“在周围函数返回之前立即运行”。您启动的任何 goroutine 都可以比该函数存活(它们不会自动停止)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go