【问题标题】:How to wait for first finished goroutine如何等待第一个完成的 goroutine
【发布时间】:2019-01-16 23:54:05
【问题描述】:

我有两种算法用于同一任务,一种最适合某些情况,另一种适合其他情况。

所以我想在处理任务时同时启动两个goroutine,并且只使用第一个完成的goroutine返回的结果。

另外,在结果中,我需要知道它是由哪个算法返回的。如果我认为第一个返回的结果不对,我想等待第二个结果。

我阅读了https://golang.org/pkg/sync/ 的文档,似乎只能等待所有goroutine完成。

如何在 golang 中实现这个想法?

【问题讨论】:

  • 让他们都将结果写入同一个通道,并使用一个例行读取结果。它们会按照在频道上发送的顺序出现。
  • 我会推荐那篇文章blog.golang.org/pipelines。我想里面有你需要的一切。

标签: go channel goroutine


【解决方案1】:

我认为您不需要使用sync,但我相信您可以想出一个可以使用的解决方案。我认为最简单的解决方案是:

  1. 为每条数据创建一个新通道。我不确定这会对性能产生什么影响,因此您可以检查一下。
  2. 向两种算法发送相同的输出通道。
  3. 取出频道中的第一个值,看看您是否喜欢它。
  4. 如果不这样做,请取第二个值。
  5. 继续,无需担心开放通道。 We have garbage collection in go

类似这样的:

type Result struct {
    Value     string
    Algorithm string
}

func (r *Result) String() string {
    return r.Value
}

func A(in string, out chan *Result) {
    out <- &Result{"A", "A"}
}

func B(in string, out chan *Result) {
    out <- &Result{"B", "B"}
}

func main() {
    data := []string{"foo", "bar", "baz"}

    for _, datum := range data {
        resultChan := make(chan *Result, 2)
        expectedResult := "B"

        go A(datum, resultChan)
        go B(datum, resultChan)

        result := <-resultChan
        if result.Value != expectedResult {
            fmt.Println("Unexpected result: ", result)
            result = <-resultChan
        }

        fmt.Println("Got result: ", result)
    }
}

【讨论】:

  • 缓冲通道或在A和B中使用带有默认子句的select语句。否则如果第一个值被认为是好的,它们中的一个将永远阻塞。
【解决方案2】:

您可以使用 Buffer Channel 来实现,简单的代码是:

package main

import (
    "fmt"
)
type Result struct {
    Value     string
    Algorithm string
}

func DoTaskA(out chan *Result) {
    out <- &Result{"A", "A"}
}

func DoTaskB(out chan *Result) {
    out <- &Result{"B", "B"}
}

func IsGood(re *Result) bool {
    return re.Value == "B"
}

func main() {
    out := make(chan *Result, 1)
    go DoTaskA(out)
    go DoTaskB(out)
    for {
        re := <- out
        if IsGood(re) {
            fmt.Println("The chosen one is:", re.Algorithm)
            return
        }
    }
}

【讨论】:

    猜你喜欢
    • 2018-02-24
    • 2019-02-01
    • 1970-01-01
    • 2015-07-05
    • 2014-11-15
    • 1970-01-01
    • 2023-04-03
    • 2017-06-22
    • 2023-04-03
    相关资源
    最近更新 更多