Go 完成一项任务后如何完成所有任务
我想运行多个goroutine,进行一些处理,将结果放入通道,当至少有一个goroutine完成时,完成所有其他goroutine并从通道返回结果 所以,我尝试使用wait组来实现这个功能,但似乎还没有正确地使用wait组Go 完成一项任务后如何完成所有任务,go,Go,我想运行多个goroutine,进行一些处理,将结果放入通道,当至少有一个goroutine完成时,完成所有其他goroutine并从通道返回结果 所以,我尝试使用wait组来实现这个功能,但似乎还没有正确地使用wait组 package optimizer import ( "github.com/tevino/abool" "errors" "sync" "runtime" "log"
package optimizer
import (
"github.com/tevino/abool"
"errors"
"sync"
"runtime"
"log"
)
type Optimizer struct {
Handlers []ofdHandler.Handler
}
func Make(handlers []ofdHandler.Handler, maxProcs int) Optimizer {
runtime.GOMAXPROCS(maxProcs)
return Optimizer{Handlers: handlers}
}
func (o Optimizer) Optimize(params operations.GetV1ReceiptsParams) (*models.Receipt, error) {
var wg sync.WaitGroup
wg.Add(len(o.Handlers))
results := make(chan *models.Receipt)
isCalculated := abool.NewBool(false)
for _, handler := range o.Handlers {
go func(handler ofdHandler.Handler) {
log.Println("Starting handler: ", handler.GetName())
defer wg.Done()
if isCalculated.IsSet() {
log.Println("Result is calculated, exiting goroutine...")
return
}
receipt, err := handler.Handle(params)
if err != nil {
log.Println(err)
return
}
if isCalculated.IsSet() {
log.Println("Result is calculated, exiting goroutine...")
return
}
log.Println("Writing result to channel...")
isCalculated.Set()
results <- receipt
}(handler)
}
log.Println("Waiting...")
wg.Wait()
if receipt, ok := <-results; ok {
return receipt, nil
}
return nil, errors.New("couldn't optimize with current list of Handlers")
}
包优化器
进口(
“github.com/tevino/abool”
“错误”
“同步”
“运行时”
“日志”
)
类型优化器结构{
Handlers[]ofdHandler.Handler
}
func Make(handlers[]ofdHandler.Handler,maxProcs int)优化器{
runtime.GOMAXPROCS(maxProcs)
返回优化器{Handlers:Handlers}
}
func(o优化器)优化(params operations.GetV1ReceiptsParams)(*models.Receipt,error){
var wg sync.WaitGroup
工作组增补(列名(o.1))
结果:=制造(成龙*型号。收据)
isCalculated:=abool.NewBool(假)
对于u,handler:=范围o.Handlers{
go func(handler.handler的处理程序){
log.Println(“启动处理程序:”,handler.GetName()
推迟工作组完成()
如果是计算的,则为{
Println(“结果已计算,正在退出goroutine…”)
返回
}
收据,错误:=handler.Handle(参数)
如果错误!=零{
log.Println(错误)
返回
}
如果是计算的,则为{
Println(“结果已计算,正在退出goroutine…”)
返回
}
Println(“将结果写入通道…”)
isCalculated.Set()
结果最好的方法是使用。在上有一个很好的示例,说明如何准确地针对您的问题类型执行此操作。您发布的代码无法按原样编译,您也没有描述问题(发生了什么而不是预期的结果),但通过查看代码,我有两个建议:
使结果通道缓冲,长度为1:
results := make(chan *models.Receipt, 1)
这允许最先完成的goroutine将结果写入cannel并退出,从而减少waitgroup的计数器
最后,您应该使用SetToIf
,而不是isCalculated.Set()
,这样您就不会将标志/结果设置两次(因此会暂停,因为读卡器仍在等待waitgroup“完成”,所以第二个goroutine将无法写入通道,这意味着waitgroup永远不会达到零):
log.Println(“将结果写入通道…”)
如果是计算的。SetToIf(false,true){
结果谢谢,@ain,成功了!顺便说一句,我应该在从中读取一个值后关闭通道吗?不需要关闭通道,因为你不迭代它,GC也不关心通道是否关闭。谢谢,我会仔细看看。你觉得blogpost怎么样?扇出,扇入
log.Println("Writing result to channel...")
if isCalculated.SetToIf(false, true) {
results <- receipt
}