time.sleep只阻塞当前goroutine,参数单位为纳秒,故time.sleep(1000)仅休眠1000纳秒(约1微秒);正确写法是time.sleep(1000 * time.millisecond)或time.sleep(time.second)。

time.Sleep 不会让整个程序“暂停”,它只阻塞当前 goroutine,且必须配合正确的参数单位才能生效。直接写 time.Sleep(1000) 是错的——那只是休眠 1000 纳秒(约 1 微秒),几乎不可察觉。
为什么 time.Sleep(1000) 不等于休眠 1 秒
time.Sleep 的参数类型是 time.Duration,本质是 int64,单位固定为纳秒。传入裸整数 1000 就是 1000 纳秒,不是毫秒也不是秒。
- ✅ 正确写法:
time.Sleep(1000 * time.Millisecond)或time.Sleep(time.Second) - ❌ 错误写法:
time.Sleep(1000)、time.Sleep(1000 * 1e6)(易读性差,还可能溢出) - ⚠️ 注意:Go 不做隐式单位转换,也不会报错,只会静默休眠极短时间,导致 goroutine 看似“没执行”
time.Sleep 在 goroutine 中的真实调度行为
调用 time.Sleep 后,当前 goroutine 会主动让出 M(OS 线程),进入 Gwaiting 状态,由 runtime 记录一个定时器,到期后通过 goready 唤醒它。这个过程不占用 CPU,也不阻塞其他 goroutine。
- 它发生在安全点(safepoint),是协作式让出,不是抢占式中断
- 即使
runtime.GOMAXPROCS(1),其他 goroutine 仍能被调度——只要它们也触发了安全点(如 chan 操作、I/O、函数调用) - 但纯计算循环(如
for {})不触发安全点,在 Go 1.14+ 虽有异步抢占(SIGURG),默认 10ms 才检查一次,仍有延迟风险
别用 time.Sleep 做 goroutine 同步
常见错误:启动 goroutine 后,用 time.Sleep 等待它完成。这不可靠,因为执行时间受调度延迟、GC、系统负载影响。
- ❌ 危险写法:
go doWork(); time.Sleep(5 * time.Second)—— 可能过早退出,也可能等太久 - ✅ 推荐替代:
sync.WaitGroup、带缓冲的chan struct{}、或context.WithTimeout - ? 补充:若只是调试观察,
time.Sleep可用;但生产代码中,它只该用于“延时触发”或“节流”,而非同步原语
真正容易被忽略的是:休眠时间越长,goroutine 在 P 的本地队列中等待唤醒的开销越小,但一旦你依赖它做逻辑时序控制(比如“等 A 完成再发 B”),就已偏离 Go 并发模型的设计意图——应该用 channel 通信驱动状态流转,而不是靠时间猜。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











