Go 完成一项任务后如何完成所有任务

Go 完成一项任务后如何完成所有任务,go,Go,我想运行多个goroutine,进行一些处理,将结果放入通道,当至少有一个goroutine完成时,完成所有其他goroutine并从通道返回结果 所以,我尝试使用wait组来实现这个功能,但似乎还没有正确地使用wait组 package optimizer import ( "github.com/tevino/abool" "errors" "sync" "runtime" "log"

我想运行多个goroutine,进行一些处理,将结果放入通道,当至少有一个goroutine完成时,完成所有其他goroutine并从通道返回结果

所以,我尝试使用wait组来实现这个功能,但似乎还没有正确地使用wait组

    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
}