我有以下代码:
func sendRegularHeartbeats(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
case <-time.After(1 * time.Second):
sendHeartbeat()
}
}
}
Run Code Online (Sandbox Code Playgroud)
此功能在专用的go-routine中执行,并每秒发送一次心跳消息.取消上下文时,整个过程应立即停止.
现在考虑以下场景:
ctx, cancel := context.WithCancel(context.Background())
cancel()
go sendRegularHeartbeats(ctx)
Run Code Online (Sandbox Code Playgroud)
这将启动具有封闭上下文的心跳例程.在这种情况下,我不希望传输任何心跳.因此,case应立即输入选择中的第一个块.
但是,似乎case无法保证评估块的顺序,并且代码有时会发送心跳消息,即使上下文已被取消.
实现这种行为的正确方法是什么?
我可以在第二个中添加"isContextclosed" - 检查case,但这看起来更像是一个丑陋的解决方法.
我在多个非缓冲通道上使用select时发现了
select {
case <- chana:
case <- chanb:
}
Run Code Online (Sandbox Code Playgroud)
即使两个通道都有数据,但在处理此选择时,如果chana和case chanb处于不平衡的调用.
package main
import (
"fmt"
_ "net/http/pprof"
"sync"
"time"
)
func main() {
chana := make(chan int)
chanb := make(chan int)
go func() {
for i := 0; i < 1000; i++ {
chana <- 100 * i
}
}()
go func() {
for i := 0; i < 1000; i++ {
chanb <- i
}
}()
time.Sleep(time.Microsecond * 300)
acount := 0
bcount := 0
wg := …Run Code Online (Sandbox Code Playgroud)