我正在尝试理解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秒钟并给它时间。这种行为似乎非常错误。
答案 0 :(得分:2)
这种行为似乎非常错误。
不是。这就是指定程序执行的方式。在main及其延迟函数返回之后,程序退出。
通过初始化主程序包然后调用函数main开始程序执行。当该函数调用返回时,程序退出。它不等待其他(非主)goroutine完成。