为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
翻过高山走不出你 2022-12-19 17:51:09
我想编写一个 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 语言。也许有更好的方法来解决我的问题。
查看完整描述

1 回答

?
桃花长相依

TA贡献1860条经验 获得超8个赞

您可以在select声明之外完成您的工作,然后在票据通道案例中继续。这将立即执行您的工作一次,然后每次自动收报机滴答作响。


您的函数看起来不错,但最好尽可能使用上下文。


许多包(数据库、IO 等)都可以选择指定上下文,这通常用于定义超时。在您的情况下,将相同(或子)上下文传递给这些包将意味着它们也尊重 sigterm。


package main


import (

    "context"

    "fmt"

    "os"

    "os/signal"

    "syscall"

    "time"

)


func main() {

    ctx := cancelCtxOnSigterm(context.Background())

    startWork(ctx)

}


// cancelCtxOnSigterm returns a Context that will be cancelled when the program receives a sigterm.

func cancelCtxOnSigterm(ctx context.Context) context.Context {

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

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


    ctx, cancel := context.WithCancel(ctx)

    go func() {

        <-exitCh

        cancel()

    }()

    return ctx

}


// startWork performs a task every 60 seconds until the context is done.

func startWork(ctx context.Context) {

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

    defer ticker.Stop()

    for {

        // Do work here so we don't need duplicate calls. It will run immediately, and again every minute as the loop continues.

        if err := work(ctx); err != nil {

            fmt.Printf("failed to do work: %s", err)

        }

        select {

        case <-ticker.C:

            continue

        case <-ctx.Done():

            return

        }

    }

}


func work(ctx context.Context) error {

    fmt.Println("doing work")

    return nil

}


查看完整回答
反对 回复 2022-12-19
  • 1 回答
  • 0 关注
  • 97 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信