0

我必须从循环中调用 goroutuine /thread。由于循环,有许多 go 例程并行执行。如果任何例程/线程成功执行,那么我必须停止所有其他线程/例程。

有什么方法可以实现吗?

4

3 回答 3

2

除了 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
        }
    }
}

于 2021-08-01T17:34:17.780 回答
2

您可以使用上下文:

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 最终都会结束。

于 2021-08-01T17:20:56.167 回答
0

您可以使用上下文和错误组。类似于...的东西

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)
    }
}
于 2021-08-03T09:13:07.737 回答