如何在Golang应用关闭时中断time.Sleep休眠?
如何在Golang应用关闭时中断休眠操作
你的问题核心在于time.Sleep是阻塞式调用,即便调用了cancel(),goroutine也要等休眠结束才会检查ctx.Done()信号,导致应用关闭延迟。要解决这个问题,需要把休眠逻辑放到select中,和ctx.Done()一起监听,这样就能在收到取消信号时立即中断等待。
修改方案
将原来的time.Sleep(1 * time.Minute)替换为通过select同时监听ctx.Done()和定时信号,具体调整如下:
- 移除直接的
time.Sleep调用,改用time.After()生成一个定时通道 - 在
select中同时处理ctx.Done()和定时事件,让取消信号能优先触发
修改后的完整代码
package main import ( "context" "fmt" "os" "os/signal" "syscall" "time" ) func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() go func() { for { select { case <-ctx.Done(): // 收到取消信号,直接退出goroutine return default: if condition { // 替换为你的实际条件判断逻辑 // do something fmt.Println("执行任务") } else { // 用select实现可中断的休眠 select { case <-ctx.Done(): return case <-time.After(1 * time.Minute): // 休眠结束,进入下一次循环检查条件 } } } } }() signChan := make(chan os.Signal, 5) signal.Notify(signChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) <-signChan cancel() time.Sleep(3 * time.Second) fmt.Println("Shutdown") }
关键说明
- 内层
select确保当ctx被取消时,不管休眠是否到期,都会立刻退出等待,避免应用关闭延迟 - 原代码中的
break仅能跳出select,无法终止for循环,改用return可直接结束goroutine - 如果需要动态调整休眠时长,也可以用
time.NewTimer创建定时器,配合Stop()避免资源泄漏(单次等待场景下time.After已足够简洁)
内容的提问来源于stack exchange,提问作者Violetta
相关产品推荐
相关产品推荐

