我必须从循环中调用 goroutuine /thread。由于循环,有许多 go 例程并行执行。如果任何例程/线程成功执行,那么我必须停止所有其他线程/例程。
有什么方法可以实现吗?
我必须从循环中调用 goroutuine /thread。由于循环,有许多 go 例程并行执行。如果任何例程/线程成功执行,那么我必须停止所有其他线程/例程。
有什么方法可以实现吗?
除了 Burak 回答的上下文之外,您还可以使用退出通道。
package main
import (
"fmt"
"math/rand"
"time"
)
func foo(channel, quit chan string, i int) {
channel <- fmt.Sprintf("goroutine %d started!", i)
for {
rand.Seed(time.Now().UnixNano())
time.Sleep(time.Duration(rand.Intn(500)+500) * time.Millisecond)
quit <- fmt.Sprintf("goRoutine %d completed!", i)
}
}
func main() {
channel := make(chan string)
quit := make(chan string)
for i := 0; i < 3; i++ {
go foo(channel, quit, i)
}
for {
select {
case update:= <-channel:
fmt.Println(update)
case quit:= <-quit:
fmt.Println(quit)
return
}
}
}
您可以使用上下文:
ctx, cancel:= context.WithCancel(context.Background())
for ... {
go func() {
defer cancel() // cancel context once this goroutine ends
doStuff(ctx)
}()
}
您必须在 goroutines 中检查上下文取消:
func doStuff(ctx context.Context) {
...
if ctx.Err()!=nil {
// Canceled, return
return
}
...
}
这并不能保证一旦上下文被取消,其他 goroutine 将立即结束,但是它保证,如果您正确检查上下文取消,所有 goroutine 最终都会结束。
您可以使用上下文和错误组。类似于...的东西
package main
import (
"context"
"fmt"
"math/rand"
"os"
"time"
"golang.org/x/sync/errgroup"
)
func doStuff(ctx context.Context, i int) error {
count := 0
for ctx.Err() == nil {
// do the stuff
time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)))
count++
if count > 6 { // error condition
fmt.Fprintf(os.Stdout, "%v reached count %v\n", i, count)
return fmt.Errorf("Error %v, count %v\n", i, count)
}
}
fmt.Fprintf(os.Stdout, "Killed %v @ count %v\n", i, count)
return ctx.Err()
}
func main() {
rand.Seed(int64(time.Now().Nanosecond()))
ctxWc, _ := context.WithCancel(context.Background())
g, ctx := errgroup.WithContext(ctxWc)
for i := 0; i < 5; i++ {
i := i
g.Go(func() error {
return doStuff(ctx, i)
})
}
err := g.Wait()
fmt.Println("The End")
if err != nil {
fmt.Println(err)
}
}