如何运行心跳函数

How to run a heartbeat function

我看到了很多关于如何定期 运行 函数的问题。 问题?他们都阻止了程序继续进行。

我需要什么? 我有一个 websocket,我有一个 for {},它一直在读取消息,现在每 10 秒我需要 运行 调用心跳函数,而不会中断程序或停止阅读聊天。 我正在考虑使用一些方法,但其中 none 似乎 clean/nice 使用渠道,但我认为更有经验的人可能有更好更简单的方法。

我正在使用类似的东西,但它永远不会到达函数的末尾 return 我需要让程序继续。

timerCh := time.Tick(time.Duration(10) * time.Second)
  for range timerCh {
    go Heartbeat(ws)
}

return ws

我正在寻找一种能够每 10 秒调用 Heartbeat 的方法,而无需:

  1. 每次读取传入的 websocket 连接时重复调用它
  2. 没有锁定程序。

一些上下文, 这是用于桥接聊天,所以我打开一个 websocket,继续阅读,并且只在聊天消息时发送到另一个聊天,同时我需要发送心跳而不锁定它。 我现在有什么? 现在一切正常,但大约 30 秒后我的 websocket 关闭:

2020/07/01 20:59:09 Error read: websocket: close 1000 (normal)

编辑:接受@JimB 的回答!这只是为了表明计时器应该在 main goroutine 之外进行管理。

您的检测信号函数应该管理自己的计时器。这样的事情应该有效:

package main

import (
    "fmt"
    "time"
)

func main() {
    go heartbeat()
    for i := 0; i < 10; i++ {
        fmt.Println("main is still going")
        time.Sleep(time.Second * 3)
    }
}

func heartbeat() {
    for {
        timer := time.After(time.Second * 10)
        <-timer
        fmt.Println("heartbeat happened!")
    }
}

此示例将每 3 秒从 main 打印一次,每 10 从心跳打印一次,并将在 30 秒后终止。

您将希望能够关闭自动收报机,所以不要使用 time.Tick,而是使用 time.NewTicker

如果将带有代码的整个 for 循环移动到一个 goroutine 中,它不会阻塞主 goroutine。

go func() {
    ticker := time.NewTicker(10 * time.Second)
    defer ticker.Stop()
    for range ticker.C {
        Heartbeat(ws)
        // return on error or cancellation
    }
}()