bod*_*ser 4 channel go coroutine wait
我sync.WaitGroup
和select
一起使用时遇到了问题.如果您查看以下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例程中获取错误?
在我写这个问题时,我得到了自己的答案,我认为这是一个有趣的案例,我想与你分享.
使用诀窍sync.WaitGroup
和chan
在一起就是我们总结:
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将始终检查错误并等待,如果没有任何反应:)