3 回答
TA贡献1887条经验 获得超5个赞
两种方式的成本都非常低。goroutines 不需要单独的操作系统线程,并且在阻塞通道接收时几乎不消耗资源,但启动的成本也很低,因此也没有充分的理由让它们保持打开状态。
我的代码很少使用工作池。通常,我的生产者会为其生成的每个工作单元生成一个 goroutine,并将其与响应通道一起直接传递出去,然后生成一个“侦听器”,它对工作输出进行一些格式化并将所有响应通过管道返回到主线程。我的常见模式如下:
func Foo(input []interface{}) resp chan interface{} {
var wg sync.WaitGroup
resp := make(chan interface{})
listen := make(chan interface{})
theWork := makeWork(input)
// do work
for _, unitOfWork := range theWork {
wg.Add(1)
go func() {
// doWork has signature:
// func doWork(w interface{}, ch chan interface{})
doWork(unitOfWork, listen)
wg.Done()
}()
}
// format the output of listen chan and send to resp chan
// then close resp chan so main can continue
go func() {
for r := range listen {
resp <- doFormatting(r)
}
close(resp)
}()
// close listen chan after work is done
go func() {
wg.Wait()
close(listen)
}()
return resp
}
然后我的主函数将一些输入传递给它并监听响应通道
func main() {
loremipsum := []string{"foo", "bar", "spam", "eggs"}
response := Foo(loremipsum)
for output := range response {
fmt.Println(output)
}
}
TA贡献1796条经验 获得超4个赞
任务队列和等待工人的模式在 Go 中很常见。Goroutines 很便宜,但执行顺序是不确定的。因此,如果您希望您的系统行为是可预测的,您最好通过循环或其他方式请求的无缓冲通道控制工作人员与主程序的会合。否则,其中一些可以生成但保持空闲状态,这是合法的。
- 3 回答
- 0 关注
- 159 浏览
添加回答
举报