如何等待第一个完成的 goroutine
How to wait for first finished goroutine
对于同一任务我有两种算法,一种对某些情况最好,另一种对其他情况最好。
所以我想在处理任务时同时启动两个goroutine,并且只使用第一个完成的goroutine返回的结果。
另外,在结果中,我需要知道它是由哪个算法返回的。如果我认为第一个返回结果不对,我想等待第二个结果。
我通读了 https://golang.org/pkg/sync/ 的文档,似乎只能等待所有 goroutine 完成。
如何在 golang 中实现这个想法?
我认为您不需要使用 sync
,但我相信您可以想出一个解决方案。我认为最简单的解决方案是:
- 为每条数据创建一个新通道。我不确定这对性能的影响,所以你可以做一些检查。
- 向两种算法发送相同的输出通道。
- 取下频道的第一个值,看看你是否喜欢它。
- 如果不这样做,取第二个值。
- 继续,不用担心开放频道。 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)
}
}
您可以使用 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
}
}
}
对于同一任务我有两种算法,一种对某些情况最好,另一种对其他情况最好。
所以我想在处理任务时同时启动两个goroutine,并且只使用第一个完成的goroutine返回的结果。
另外,在结果中,我需要知道它是由哪个算法返回的。如果我认为第一个返回结果不对,我想等待第二个结果。
我通读了 https://golang.org/pkg/sync/ 的文档,似乎只能等待所有 goroutine 完成。
如何在 golang 中实现这个想法?
我认为您不需要使用 sync
,但我相信您可以想出一个解决方案。我认为最简单的解决方案是:
- 为每条数据创建一个新通道。我不确定这对性能的影响,所以你可以做一些检查。
- 向两种算法发送相同的输出通道。
- 取下频道的第一个值,看看你是否喜欢它。
- 如果不这样做,取第二个值。
- 继续,不用担心开放频道。 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)
}
}
您可以使用 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
}
}
}