猿问

如何实现带有在第一个循环中立即运行的定时器的for循环机制?

我想编写一个 golang 程序,在 kubernetes 的容器中作为服务运行。该程序应该一直运行而不是自行终止——除非出现错误。如果 SIGTERM 来自 kubelet / kubernetes 因为 pod 应该被删除,程序应该退出。


在我的第一种方法中,我实现了一个应该每分钟运行一次的 for 循环。在这个循环中,程序从另一个服务中查询资源并对其进行处理。然后服务应该“休眠”一分钟,然后再次执行这些步骤。在“睡眠”阶段,如果有 SIGTERM,程序应该立即响应。


func main() {

  

  c := make(chan os.Signal, 1)

  signal.Notify(c, os.Interrupt, syscall.SIGTERM)


  //restart loop every minute 

  ticker := time.NewTicker(60 * time.Second)

  defer ticker.Stop()


  // while true loop

  for {

    select {

    case <-c:

      fmt.Println("Break the loop")

      return

    case <-ticker.C:

      fmt.Println("Hello in a loop")

    }

  }

}

我目前的方法有两个问题。首先,我第一次运行 for 循环时必须等待一分钟。我可以以某种方式配置它,以便计时器仅在第一次运行后运行吗?


第二个问题是程序不应该在运行之间做任何事情——除了对 SIGTERM 做出反应。


我不确定我解决问题的方法是否正确。我刚刚开始使用 GO 语言。也许有更好的方法来解决我的问题。


翻过高山走不出你
浏览 135回答 1
1回答

桃花长相依

您可以在select声明之外完成您的工作,然后在票据通道案例中继续。这将立即执行您的工作一次,然后每次自动收报机滴答作响。您的函数看起来不错,但最好尽可能使用上下文。许多包(数据库、IO 等)都可以选择指定上下文,这通常用于定义超时。在您的情况下,将相同(或子)上下文传递给这些包将意味着它们也尊重 sigterm。package mainimport (&nbsp; &nbsp; "context"&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "os"&nbsp; &nbsp; "os/signal"&nbsp; &nbsp; "syscall"&nbsp; &nbsp; "time")func main() {&nbsp; &nbsp; ctx := cancelCtxOnSigterm(context.Background())&nbsp; &nbsp; startWork(ctx)}// cancelCtxOnSigterm returns a Context that will be cancelled when the program receives a sigterm.func cancelCtxOnSigterm(ctx context.Context) context.Context {&nbsp; &nbsp; exitCh := make(chan os.Signal, 1)&nbsp; &nbsp; signal.Notify(exitCh, os.Interrupt, syscall.SIGTERM)&nbsp; &nbsp; ctx, cancel := context.WithCancel(ctx)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; <-exitCh&nbsp; &nbsp; &nbsp; &nbsp; cancel()&nbsp; &nbsp; }()&nbsp; &nbsp; return ctx}// startWork performs a task every 60 seconds until the context is done.func startWork(ctx context.Context) {&nbsp; &nbsp; ticker := time.NewTicker(60 * time.Second)&nbsp; &nbsp; defer ticker.Stop()&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; // Do work here so we don't need duplicate calls. It will run immediately, and again every minute as the loop continues.&nbsp; &nbsp; &nbsp; &nbsp; if err := work(ctx); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("failed to do work: %s", err)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <-ticker.C:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; case <-ctx.Done():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}func work(ctx context.Context) error {&nbsp; &nbsp; fmt.Println("doing work")&nbsp; &nbsp; return nil}
随时随地看视频慕课网APP

相关分类

Go
我要回答