




time.Sleep仅阻塞当前goroutine,其他goroutine仍运行;单位必须显式指定如time.Second,避免误写为纳秒;不可取消,需中断时应使用time.AfterFunc或time.NewTimer。
这是最常被误解的一点:time.Sleep 只会让调用它的那个 goroutine 暂停,其他 goroutine 照常运行。如果你在 main 函数里直接调用它,看起来像“程序卡住”,其实是 main goroutine 在等,而其他启动的 goroutine(比如用 go func() {...}() 启动的)仍可执行。
time.Duration,必须显式转换,比如 time.Second、time.Millisecond * 500
time.Sleep(1000),单位错误会导致休眠 1000 纳秒Go 的 time.Sleep 接收的是 time.Duration 类型,底层是 int64,单位为纳秒。写数字字面量不加单位后缀,会被当作纳秒处理——time.Sleep(1000) 实际只休眠 1 微秒(1000 纳秒),远小于预期。
time.Sleep(1 * time.Second)、time.Sleep(500 * time.Millisecond)
time.Sleep(1000)、time.Sleep(5)(都极短,难调试)time.Second 等常量,避免手算和精度丢失time.AfterFunc 或 time.NewTimer
time.Sleep 不可中断;一旦开始,只能等完。若需响应外部信号(如用户中断、超时控制、上下文取消),应避开 time.Sleep,改用带 channel 的机制。
time.AfterFunc(d, f):延时后执行函数,返回的 *Timer 可调用 Stop() 取消timer := time.NewTimer(2 * time.Second); select { case :配合 select 实现可取消等待time.After(d) 返回的 channel 无法取消,仅适用于“一次性、不可撤回”的延时ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel()timer := time.NewTimer(5 * time.Second) defer timer.Stop()
select { case <-timer.C: fmt.Println("delay completed") case <-ctx.Done(): fmt.Println("can
celed due to timeout") }
time.Sleep 要防时间漂移如果写一个每秒执行一次的任务:for { doWork(); time.Sleep(time.Second) },实际间隔会略大于 1 秒(因为 doWork() 耗时也被计入)。长期运行可能越拖越慢。
next := time.Now().Add(time.Second),每次 time.Sleep(next.Sub(time.Now())),再更新 next
time.Ticker,它内部已处理时钟漂移校准time.Ticker 不适合单次延时,但循环定时任务首选它真正要注意的不是“怎么睡”,而是“谁在睡、能不能醒、醒了之后还准不准”。尤其在服务端或 CLI 工具里混用 time.Sleep 和 context 控制时,漏掉取消路径很容易导致 goroutine 泄漏或响应僵死。