为了账号安全,请及时绑定邮箱和手机立即绑定

从 goroutine 之外停止 goroutine

从 goroutine 之外停止 goroutine

Go
慕少森 2022-06-27 15:30:44
我在这里有一个 go 例程,当上下文过期时,它需要从外部 go 例程中停止。但是,当上下文过期时,go 例程不会停止,并且会继续运行,即使控制它的 go 例程停止也是如此。package mainimport (    "context"    "fmt"    "time")func main() {    ctxParent := context.Background()    ch := make(chan bool)    d := 5 * time.Second    ctx, cancel := context.WithTimeout(ctxParent, d)    defer cancel()    go doSomething(ctx, ch)    // go func() {    select {    // done    case _ = <-ch:        fmt.Println("goroutine finished")    }    fmt.Println("waiting 11 seconds on main thread, ending all go routines")    time.Sleep(11 * time.Second)    fmt.Println(">>>> END")}func doSomething(ctx context.Context, ch chan<- bool) {    // how to kill this go routine if context expires??    go func(ctx context.Context) {        fmt.Println("LOTS OF WORK TIME..")        for i := 0; i < 1000; i++ {            time.Sleep(1 * time.Second) // LOTS OF WORK            fmt.Println(i)        }    }(ctx)    select {    case _ = <-ctx.Done():        fmt.Println("*** Go routine timed out in 5 seconds!!! ****")        ch <- true        return    }}这将打印(https://play.golang.org/p/L8u51odiHxS)LOTS OF WORK TIME..01234*** Go routine timed out in 5 seconds!!! ****goroutine finishedwaiting 11 seconds on main thread, ending all go routines56789101112131415>>>> END它不应该打印 5,6,7,8... 等等。有没有办法杀死这个内部 go 例程?
查看完整描述

2 回答

?
慕妹3242003

TA贡献1824条经验 获得超6个赞

您必须在 goroutine 中检查上下文过期/取消:


 go func(ctx context.Context) {

        fmt.Println("LOTS OF WORK TIME..")

        for i := 0; i < 1000; i++ {

            select {

              case <-ctx.Done():

                  return

              default:

            }

            time.Sleep(1 * time.Second) // LOTS OF WORK

            fmt.Println(i)

        }


    }(ctx)


查看完整回答
反对 回复 2022-06-27
?
DIEA

TA贡献1820条经验 获得超2个赞

就像 Burak Serdar 所说,你必须检查 goroutine 中上下文的状态,但不仅仅是在 goroutine 开始时:你必须在 goroutine 中定期检查。


go func(ctx context.Context) {

  for i := 0; i < 1000; i++ {

    select {

    case <-ctx.Done():

      return

    default:

      // do some work

    }

  }

}(ctx)

一般来说,不应该从外部杀死一个 goroutine;它必须自己检查并意识到时间到了。


查看完整回答
反对 回复 2022-06-27
  • 2 回答
  • 0 关注
  • 104 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信