优先考虑 Go select 语句
问题:
在 Go select 语句中,顺序案例块的评估是不确定的。这可能会导致即使相应的通道已准备好接收,也无法立即输入特定 case 块的情况。
场景:
考虑 sendRegularHeartbeats()定期发送心跳消息并在其上下文被取消时终止的函数。如果在发送第一个心跳消息之前取消上下文,我们预计不会传输任何心跳消息。
非确定性评估问题:
在某些情况下,尽管在函数启动之前上下文已取消,但仍会发送心跳消息。这是因为评估的顺序是不可预测的,并且默认情况或心跳情况可能会在上下文情况之前输入。
不正确的建议:
一个建议的解决方案是添加“isContextclose”-检查心跳情况。然而,这不是一个可靠的解决方案,因为上下文和心跳通道都可以同时准备好读取。
建议的解决方案:原始选择
优先考虑上下文情况,我们可以引入一个原始的 select 语句来测试上下文通道是否准备就绪。只有当上下文通道没有准备好时,才会执行第二个 select 语句。
func sendRegularHeartbeats(ctx context.Context) { for { // Primordial select: Check for context channel being ready only. select { case <-ctx.Done(): return default: } // Secondary select: Handle heartbeat logic. select { case <-ctx.Done(): return case <-time.After(1 * time.Second): sendHeartbeat() } } }
不完美:
虽然这种方法有效地优先考虑了上下文情况,但它可能仍然允许“足够接近”的事件。例如,如果在上下文通道准备好之后不久心跳事件到达,则可以在进入上下文情况之前发送心跳。目前的Go语言实现还没有完美的解决这个问题。
以上是如何保证 Go 的 select 语句中上下文取消的优先级?的详细内容。更多信息请关注PHP中文网其他相关文章!