Go 的 Select 語句中的優先權控制
在 Go 中,select 語句允許 goroutine 之間進行非同步通訊。然而,case 區塊的評估順序有時會導致意外的結果。當嘗試優先處理特定情況時,例如在取消上下文時立即退出例程,就會出現此問題。
考慮以下程式碼:
func sendRegularHeartbeats(ctx context.Context) { for { select { case <-ctx.Done(): return case <-time.After(1 * time.Second): sendHeartbeat() } } }
問題:
在此程式碼中,目的是優先處理ctx.Done() 情況而不是time.After () 情況。然而,由於 Go 的不確定性評估順序,有時可能會先評估 time.After() 情況,從而導致即使上下文被取消也會傳輸心跳。
解決方案:
接受的答案中提出的解決方案建議添加嵌套的 select 語句,並對 ctx.Done() 進行非阻塞檢查。然而,這並不能完全解決問題,因為發送心跳的機率仍然很高。
更有效的方法是透過新增預設情況來優先處理ctx.Done() 情況外部select 語句:
func sendRegularHeartbeats(ctx context.Context) { ticker := time.NewTicker(time.Second) defer ticker.Stop() for { select { case <-ctx.Done(): return default: } select { case <-ctx.Done(): return case <-ticker.C: sendHeartbeat() } } }
這確保了ctx.Done() 情況在外部select 語句中首先被評估,從而賦予它更高的優先權。如果上下文被取消,例程將立即返回並且不會發送任何心跳。如果 time.After() 的情況先到達,由於外部 select 語句中的預設情況,它將被忽略。
以上是如何在 Go 的 select 語句中優先考慮上下文取消?的詳細內容。更多資訊請關注PHP中文網其他相關文章!