golang ctx cancel 没有按预期工作

golang ctx cancel not working as expected

func main() {
    fmt.Println("Hello, playground")
    ctx, cancel := context.WithCancel(context.Background())
    func(ctx context.Context) {

        for _, i := range []int{1, 2, 3, 4, 5} {
            go func(ctx context.Context, i int) {
                for {
                    fmt.Println("go routine#", i)
                }

            }(ctx, i)
        }
    }(ctx)
    fmt.Println("before cancel num goroutines", runtime.NumGoroutine())
    time.Sleep(1 * time.Millisecond)
    cancel()

    fmt.Println("after cancel num goroutines", runtime.NumGoroutine())
}

输出:-

./ctxCancel 
Hello, playground
before cancel num goroutines 6
go routine# 5
go routine# 5
...
after cancel num goroutines 6
go routine# 1
go routine# 1
go routine# 1
go routine# 1
go routine# 2

正如在上面的输出中所注意到的,我看到 numof goroutines 在调用上下文的取消函数后仍然相同。您甚至可以在取消函数调用后看到 goroutine 的输出。 我的期望是调用 cancel 函数将终止传递此 ctx 的 go 例程。请帮助我理解上下文取消函数的行为。

上下文取消只是关闭一个通道。你的 goroutines 应该检查上下文是否被取消,并且 return.

            go func(ctx context.Context, i int) {
                for {
                    select {
                        case <-ctx.Done():
                           return
                        default:
                     }
                    fmt.Println("go routine#", i)
                }

            }(ctx, i)

取消后,您应该等待 goroutines 终止。他们不会立即收到取消通知。