You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 23:47:22