上下文取消不退出
context cancel does not exit
预计:大约在2 秒
实际:无限期运行。
不明白是什么导致它无限期地 运行。
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
for i := range generator(ctx) {
select {
case <-time.After(2 * time.Second):
cancel()
return
default:
fmt.Println(i)
}
}
}
func generator(ctx context.Context) <-chan int {
ch := make(chan int)
go func() {
count := 0
for {
select {
case <-ctx.Done():
return
case ch <- count:
count++
}
}
}()
return ch
}
主要问题是您从 generator(ctx)
返回的频道发出值的速度几乎与您读取它们的速度一样快。
time.After(2 * time.Second)
创建的通道几乎立即被丢弃,您通过生成器每次迭代创建一个新的超时通道。
如果你做一个小小的改变;在循环 外部 创建超时通道,然后将其放入 select 子句中,您将看到它开始工作。
timeout := time.After(2 * time.Second)
for i := range generator(ctx) {
select {
case <-timeout:
cancel()
return
default:
fmt.Println(i)
}
}
预计:大约在2 秒
实际:无限期运行。
不明白是什么导致它无限期地 运行。
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
for i := range generator(ctx) {
select {
case <-time.After(2 * time.Second):
cancel()
return
default:
fmt.Println(i)
}
}
}
func generator(ctx context.Context) <-chan int {
ch := make(chan int)
go func() {
count := 0
for {
select {
case <-ctx.Done():
return
case ch <- count:
count++
}
}
}()
return ch
}
主要问题是您从 generator(ctx)
返回的频道发出值的速度几乎与您读取它们的速度一样快。
time.After(2 * time.Second)
创建的通道几乎立即被丢弃,您通过生成器每次迭代创建一个新的超时通道。
如果你做一个小小的改变;在循环 外部 创建超时通道,然后将其放入 select 子句中,您将看到它开始工作。
timeout := time.After(2 * time.Second)
for i := range generator(ctx) {
select {
case <-timeout:
cancel()
return
default:
fmt.Println(i)
}
}