GODEBUG設定`asynctimerchan`がGo 1.27で完全に削除され、time パッケージのタイマーチャンネルは常に同期(非バッファ)動作に統一された。
Runtime
概要
Go 1.23で導入された asynctimerchan GODEBUG 設定が、Go 1.27で恒久的に削除された。これにより time パッケージが生成するタイマーチャンネル(Timer.C・Ticker.C)は、GODEBUG の値に関わらず常に同期(非バッファ、容量0相当)で動作する。
移行時の注意
GODEBUG=asynctimerchan=1(Go 1.22以前の非同期・バッファ付き動作)または asynctimerchan=2(Go 1.23の移行用中間値)を指定して起動時の互換動作に頼っていたコードは、Go 1.27では非デフォルト値の指定自体がビルドエラーになる。Stop/Reset 後に古いタイマー値をチャンネルから読み出してしまう可能性を前提にしたドレイン処理(select 文での default 節を用いた読み捨てなど)が残っている場合は、そのコードを削除して問題ないか確認するとよい。
実装解説
internal/godebugs パッケージの削除済み設定テーブルに asynctimerchan のエントリが追加されており、Go 1.27で削除され、旧値("1"または"2")を指定するとビルド時にエラーとなることが定義されている(internal/godebugs/table.go)。
time.NewTimer/time.NewTicker は内部で syncTimer というヘルパーを介してチャンネルを渡しており、これによってランタイム側のタイマー実装がそのチャンネルを「同期チャンネル」として扱う(time/sleep.go)。ランタイム側では runtime.timer 構造体の isChan フィールドを持つタイマーに対して blockTimerChan/unblockTimerChan(いずれも runtime/time.go)がチャンネル操作(runtime/chan.go の受信・select 処理)と連動し、受信側がブロックしている間だけタイマーをヒープに登録して送信を同期させる仕組みになっている。asynctimerchan 削除に伴い、この同期パスが唯一の経路となった。