如何使用WaitGroup处理工作池中的错误?

bod*_*ser 4 channel go coroutine wait

sync.WaitGroupselect一起使用时遇到了问题.如果您查看以下http请求池,您会注意到如果发生错误,它将永远不会被报告为wg.Done()阻止,并且不再从该通道读取.

package pool

import (
    "fmt"
    "log"
    "net/http"
    "sync"
)

var (
    MaxPoolQueue  = 100
    MaxPoolWorker = 10
)

type Pool struct {
    wg *sync.WaitGroup

    queue  chan *http.Request
    errors chan error
}

func NewPool() *Pool {
    return &Pool{
        wg: &sync.WaitGroup{},

        queue:  make(chan *http.Request, MaxPoolQueue),
        errors: make(chan error),
    }
}

func (p *Pool) Add(r *http.Request) {
    p.wg.Add(1)

    p.queue <- r
}

func (p *Pool) Run() error {
    for i := 0; i < MaxPoolWorker; i++ {
        go p.doWork()
    }

    select {
    case err := <-p.errors:
        return err
    default:
        p.wg.Wait()
    }

    return nil
}

func (p *Pool) doWork() {
    for r := range p.queue {
        fmt.Printf("Request to %s\n", r.Host)

        p.wg.Done()

        _, err := http.DefaultClient.Do(r)

        if err != nil {
            log.Fatal(err)

            p.errors <- err
        } else {
            fmt.Printf("no error\n")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

来源可以在这里找到

我怎样才能使用WaitGroup但是也可以从go例程中获取错误?

bod*_*ser 5

在我写这个问题时,我得到了自己的答案,我认为这是一个有趣的案例,我想与你分享.

使用诀窍sync.WaitGroupchan在一起就是我们总结:

select {
    case err := <-p.errors:
        return err
    default:
        p.wg.Done()
}
Run Code Online (Sandbox Code Playgroud)

一起for循环:

for {
    select {
        case err := <-p.errors:
            return err
        default:
            p.wg.Done()
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,select将始终检查错误并等待,如果没有任何反应:)