golang ctx cancel not working as expected

1.9k views Asked by At
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())
}

output:-

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

As noticed in the output above i see that numof goroutines is still the same after calling context's cancel function. You can even see the goroutine's prints after the cancel function call. My expectation was that calling cancel function would terminate the go routines to which this ctx is passed. Plz help me understand the behaviour of context's cancel function.

1

There are 1 answers

1
Burak Serdar On BEST ANSWER

Context cancel simply closes a channel. Your goroutines should check if the context is canceled, and return.

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

            }(ctx, i)

After you cancel, you should wait for the goroutines to terminate. They will not all receive the cancellation immediately.