登录
首页 >  Golang >  Go问答

当 go 程序遇到多个错误时会引发 panic

来源:stackoverflow

时间:2024-03-03 11:27:24 440浏览 收藏

怎么入门Golang编程?需要学习哪些知识点?这是新手们刚接触编程时常见的问题;下面golang学习网就来给大家整理分享一些知识点,希望能够给初学者一些帮助。本篇文章就来介绍《当 go 程序遇到多个错误时会引发 panic》,涉及到,有需要的可以收藏一下

问题内容

我正在使用工作池,我想在返回错误之前合并工作池中的所有错误。我已经编写了示例代码,但我陷入了僵局。

我想实现什么目标? 客户端发送 100 个请求,我想首先将这些请求添加到作业队列并将其分派到 n 个在后台执行任务的 go 例程,如果有错误,我想在发送所有错误之前累积所有这些错误给客户。我写了一个片段,有人可以解释一下出了什么问题以及如何缓解僵局。

package main

import (
    "context"
    "fmt"
    "sync"
    "sync/atomic"
    "time"

    "github.com/apex/log"
    "github.com/hashicorp/go-multierror"
)

type Manager struct {
    taskChan    chan int
    wg          *sync.WaitGroup
    QuitChan    chan bool
    ErrorChan   chan error
    busyWorkers int64
}

func main() {
    fmt.Println("Hello, 世界")
    m := New()

    ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
    //defer cancel()
    for i := 0; i < 3; i++ {
        m.wg.Add(1)
        go m.run(ctx, test)
    }

    for i := 1; i < 5; i++ {
        m.taskChan <- i
    }
    close(m.taskChan)
    go func(*Manager) {
        if len(m.taskChan) == 0 {
            m.QuitChan <- true
        }
    }(m)

    var errors error
    for {
        select {
        case err := <-m.ErrorChan:
            errors = multierror.Append(errors, err)
            if m.busyWorkers == int64(0) {
                break
            }
        default:
            fmt.Println("hello")
        }
    }
    m.wg.Wait()
    fmt.Println(errors)

}
func New() *Manager {
    return &Manager{taskChan: make(chan int),
        wg:        new(sync.WaitGroup),
        QuitChan:  make(chan bool),
        ErrorChan: make(chan error),
    }
}

func (m *Manager) run(ctx context.Context, fn func(a, b int) error) {
    defer m.wg.Done()
    defer fmt.Println("finished working")
    for {
        select {
        case t, ok := <-m.taskChan:
            if ok {
                atomic.AddInt64(&m.busyWorkers, 1)
                err := fn(t, t)
                if err != nil {

                    m.ErrorChan <- err
                }
                atomic.AddInt64(&m.busyWorkers, -1)
            }

        case <-ctx.Done():
            log.Infof("closing channel %v", ctx.Err())
            return
        case <-m.QuitChan:

            return
        }

    }
}
   // this can return error or not, this is the main driver func, but i'm propagating 
    //errors so that i can understand where i am going wrong
func test(a, b int) error {
    fmt.Println(a, b)
    return fmt.Errorf("dummy error %v", a)

}

正确答案


您有 3 个工作人员,他们都返回错误。

您的主线程尝试将 5 个作业放入队列中。一旦您的工作线程获取了前 3 个工作线程,主线程就会陷入等待新工作线程在 taskchan 上接收的情况,并且您的所有 3 个工作线程都会陷入尝试在 errorchan 上发送数据的情况。

换句话说,死锁。

也许您想让 taskchan 成为缓冲通道?这样您就可以在缓冲区满之前发送数据而不会阻塞。

taskChan: make(chan int, 10)

理论要掌握,实操不能落!以上关于《当 go 程序遇到多个错误时会引发 panic》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>