从main返回后,Gorutine没有完成执行。为什么?

时间:2019-05-02 12:14:21

标签: go goroutine

我正在尝试理解golang中的上下文。我从https://golang.org/pkg/context/#example_WithCancel复制了一个示例,并对其进行了一些更改: Playgroud:https://play.golang.org/p/Aczc2CqcVZR

package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    // gen generates integers in a separate goroutine and
    // sends them to the returned channel.
    // The callers of gen need to cancel the context once
    // they are done consuming generated integers not to leak
    // the internal goroutine started by gen.
    gen := func(ctx context.Context) <-chan int {
        dst := make(chan int)
        n := 1
        go func() {
            for {
                select {
                case <-ctx.Done():
                    fmt.Println("DONE")
                    return // returning not to leak the goroutine
                case dst <- n:
                    n++
                }
            }
            fmt.Println("END")
        }()
        return dst
    }

    ctx, cancel := context.WithCancel(context.Background())

    defer time.Sleep(1 * time.Second)
    defer fmt.Println("Before cancel")
    defer cancel() // cancel when we are finished consuming integers
    defer fmt.Println("After cancel")

    channel := gen(ctx)
    for n := range channel { 
        fmt.Println(n)
        if n == 5 {

            break
        }
    }

    fmt.Println( <-channel)

}

注释掉

defer time.Sleep(1 * time.Second)

“完成”永远不会被打印。 Playgroud:(https://play.golang.org/p/K0OcyZaj_xK

我希望在匿名函数中启动的go例程仍然有效。一旦由于延迟而调用cancel(),则select不应再阻塞为

case <-ctx.Done():

应该可用。但是,它似乎刚刚结束,除非我等待1秒钟并给它时间。这种行为似乎非常错误。

1 个答案:

答案 0 :(得分:2)

  

这种行为似乎非常错误。

不是。这就是指定程序执行的方式。在main及其延迟函数返回之后,程序退出。

  

通过初始化主程序包然后调用函数main开始程序执行。当该函数调用返回时,程序退出。它不等待其他(非主)goroutine完成。

https://golang.org/ref/spec#Program_execution