完整內容在此, 幹話王_Go synctest:徹底解決並發測試的痛點
Go 語言以 goroutine 和 channel 聞名,併發測試場景卻常常讓人頭痛:
sleep 不夠會 fail,sleep 太久拖慢 CI,偶發錯誤難以重現。Go 1.24 開始,提供了一個令人振奮的實驗性測試新功能:
synctest
。
讓這一切成為過去!!預計將在 8 月釋出的 Go 1.25 正式釋出。
讓我們看一個常見的例子:
假設你要測試一個 goroutine 工作是否如期完成。
func TestWorker(t *testing.T) {
done := make(chan struct{})
go func() {
// do some work
time.Sleep(100 * time.Millisecond)
close(done)
}()
time.Sleep(150 * time.Millisecond) // 等 goroutine 做完
select {
case <-done:
// ok
default:
t.Fatal("worker 未完成")
}
}
你只能靠 sleep「猜」goroutine 完成的時機
sleep 太短測試會 fail,太長又浪費時間
在 CI 跑多次還是可能偶爾 fail
很難精確同步 goroutine 狀態
synctest
的核心在於「泡泡」(bubble)與「穩定阻塞」(durably blocked)同步模型。
用 synctest.Run
包起來的程式碼和其 goroutine,會被放進一個「泡泡」
泡泡內的 goroutine 只能互相影響,和外部世界隔離
泡泡追蹤所有在裡面建立的 channel、timer、WaitGroup 等同步物件
當泡泡裡所有 goroutine 都卡住,而且只能被泡泡內其他 goroutine 喚醒,這時就叫做「穩定阻塞」
這時呼叫 synctest.Wait()
會立刻返回
若泡泡內沒有人能再被解鎖,代表死鎖,Run
會 panic
若有 timer 等待,fake clock 會自動快轉到下一個事件
完整內容在此, 幹話王_Go synctest:徹底解決並發測試的痛點