Go Runtime(十):Timer实现

本文源码基线为 Go 1.26.2、Linux/amd64。Go 1.23 重写了 Timer Channel 的可回收性与 Stop/Reset 保证;新语义是否默认生效还取决于主模块的 go 版本和 godebug/GODEBUG 设置,不能只看工具链版本。 Timer 同时服务 time.Sleep、time.Timer、time.Ticker、AfterFunc 和网络 Deadline。到期、Stop、Reset 和 Channel 的语义还会受到模块版本与调试开关影响。 先锁定可观察语义 time.NewTimer 的源码仍写 make(chan Time, 1)。新模式(asynctimerchan=0)下 runtime 借助 hchan.timer 对外呈现同步、容量为零的语义;asynctimerchan=1 恢复 Go 1.23 以前的异步 Timer Channel 行为。因此不能只看 make 参数或 go version 推断 cap(t.C) 和 Stop/Reset 语义。 三种有效模式对程序呈现的差异是: asynctimerchan Channel语义 Stop/Reset返回后的旧值 未到期且不可达的Timer 0 同步,cap(C) == 0 保证不会收到 可以被GC回收 1 Go 1.23以前的异步路径,cap(C) == 1 可能收到 不能在到期或Stop前被GC回收 2 runtime新实现,但呈现异步语义,cap(C) == 1 可能收到 可以被GC回收 这里的“从 Go 1.23 起”是模块语义版本,不只是所用 toolchain 的版本。asynctimerchan 在 internal/godebugs 表中标记为 Go 1.23 变更项,旧于 go 1.23 的主模块默认取旧值 1;go 1.23 及更新主模块默认取新值 0。go.mod/go.work 的 godebug 指令、源码中的 //go:debug 或进程环境 GODEBUG 都可以显式覆盖它。调试 Timer 时必须记录最终构建配置。 ...

August 18, 2026