从 goroutine 之外停止 goroutine

我在这里有一个 go 例程,当上下文过期时,它需要从外部 go 例程中停止。但是,当上下文过期时,go 例程不会停止,并且会继续运行,即使控制它的 go 例程停止也是如此。


package main


import (

    "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..

0

1

2

3

4

*** Go routine timed out in 5 seconds!!! ****

goroutine finished

waiting 11 seconds on main thread, ending all go routines

5

6

7

8

9

10

11

12

13

14

15

>>>> END

它不应该打印 5,6,7,8... 等等。有没有办法杀死这个内部 go 例程?


慕少森
浏览 130回答 2
2回答

慕妹3242003

您必须在 goroutine 中检查上下文过期/取消:&nbsp;go func(ctx context.Context) {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("LOTS OF WORK TIME..")&nbsp; &nbsp; &nbsp; &nbsp; for i := 0; i < 1000; i++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case <-ctx.Done():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(1 * time.Second) // LOTS OF WORK&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(i)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }(ctx)

DIEA

就像 Burak Serdar 所说,你必须检查 goroutine 中上下文的状态,但不仅仅是在 goroutine 开始时:你必须在 goroutine 中定期检查。go func(ctx context.Context) {&nbsp; for i := 0; i < 1000; i++ {&nbsp; &nbsp; select {&nbsp; &nbsp; case <-ctx.Done():&nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; // do some work&nbsp; &nbsp; }&nbsp; }}(ctx)一般来说,不应该从外部杀死一个 goroutine;它必须自己检查并意识到时间到了。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go