package main
import (
"context"
"fmt"
)
func gen(ctx context.Context) <-chan interface{} {
ch := make(chan interface{})
go func() {
n := 0
for {
select {
case <-ctx.Done():
fmt.Println("done")
default:
n += 1
ch <- n
}
}
}()
return ch
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
for n := range gen(ctx) {
fmt.Println(n)
if n == 5 {
break
}
}
defer cancel()
}
期望 能打印出 "done"
应该是阻塞在 ch<-n 了。
cancel() 如果执行的比较晚,在 cancel 之前第六个 ch<-n 就已经执行了的话,就阻塞了。(main 逻辑相对比较长,比如还有一个 Println ,所以大概率 cancel 会比较晚。
可以试试这个:
这个依然会打印 6 个,因为 cancel 的时候第六个 ch<-n 已经执行了。