Linux 如何运行heartbeat函数

Linux 如何运行heartbeat函数,linux,go,websocket,gorilla,heartbeat,Linux,Go,Websocket,Gorilla,Heartbeat,我看到了大量关于如何定期运行函数的问题和回答。问题出在哪里?他们都锁定了程序,使其无法继续运行 我需要什么? 我有一个websocket和一个for{},它一直在读msg,现在和每10秒我需要运行一次对heartbeat函数的调用,而不会中断程序或停止阅读聊天。 我正在考虑使用一些方法,但没有一种方法在使用频道时看起来干净/好,但我认为更有经验的人可能会有一种更好、更简单的方法 我曾经使用过类似的东西,但它永远不会到达函数的末尾,返回程序继续运行所需的内容 timerCh := time.Tic

我看到了大量关于如何定期运行函数的问题和回答。问题出在哪里?他们都锁定了程序,使其无法继续运行

我需要什么? 我有一个websocket和一个for{},它一直在读msg,现在和每10秒我需要运行一次对heartbeat函数的调用,而不会中断程序或停止阅读聊天。 我正在考虑使用一些方法,但没有一种方法在使用频道时看起来干净/好,但我认为更有经验的人可能会有一种更好、更简单的方法

我曾经使用过类似的东西,但它永远不会到达函数的末尾,返回程序继续运行所需的内容

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

return ws
我正在寻找一种方法,可以每10秒调用一次Heartbeat,而不需要:

每次读到传入的websocket连接时都会重复调用它 没有锁定程序。 在某种背景下, 这是一个网桥聊天,所以我打开一个websocket,继续阅读,只在聊天消息出现时发送到另一个聊天,同时我需要发送一个心跳,而不锁定它。 我现在有什么? 现在一切正常,但大约30秒后,我的websocket关闭:

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

编辑:使用@JimB的答案!这只是为了表明计时器应该在主goroutine之外进行管理

go func() {
    ticker := time.NewTicker(10 * time.Second)
    defer ticker.Stop()
    for range ticker.C {
        Heartbeat(ws)
        // return on error or cancellation
    }
}()
您的heartbeat函数应该管理自己的计时器。像这样的方法应该会奏效:

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秒从heartbeat打印一次,并将在30秒后终止。

编辑:按照@JimB的答案进行!这只是为了表明计时器应该在主goroutine之外进行管理

go func() {
    ticker := time.NewTicker(10 * time.Second)
    defer ticker.Stop()
    for range ticker.C {
        Heartbeat(ws)
        // return on error or cancellation
    }
}()
您的heartbeat函数应该管理自己的计时器。像这样的方法应该会奏效:

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秒从heartbeat打印一次,并在30秒后终止。

您希望能够关闭股票代码,因此不要使用time.Tick,而是使用time.NewTicker

如果您使用ticker将整个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
    }
}()

您将希望能够关闭股票代码,因此不要使用time.Tick,而是使用time.NewTicker

如果您使用ticker将整个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
    }
}()

为什么不把for循环放在goroutine中?从websocket读取的那个?因为它会持续不断地发出声音,我不希望这样,只希望每隔10秒左右。如果我添加一个计时器。滴答声然后停止主go例程…这不是你使用滴答器的原因,所以它只每10秒运行一次吗?你也应该有一些方法来取消这个,而且你不应该占用时间。勾选,因为正如文档所述,你不能关闭它嗯,也许这就是问题所在,我是一个新手,你能给我一个不会锁定我程序其余部分的示例吗?谢谢为什么不把for循环放在goroutine中?从websocket读取的那个?因为它会持续不断地发出声音,我不希望这样,只希望每隔10秒左右。如果我添加一个计时器。滴答声然后停止主go例程…这不是你使用滴答器的原因,所以它只每10秒运行一次吗?你也应该有一些方法来取消这个,而且你不应该占用时间。勾选,因为正如文档所述,你不能关闭它嗯,也许这就是问题所在,我是一个新手,你能给我一个不会锁定我程序其余部分的示例吗?Thanks@rek2:你不应该把时间用作睡眠,也不应该在这里使用睡眠。你最初使用股票代码的想法是正确的,你只是想阻止它。我只是在我的玩具示例中使用了sleep,我绝对不建议在代码中添加sleep@rek2使用@JimB下面的方法。我不是指实际的睡眠呼叫,你使用的是时间。After作为睡眠,并在应该使用间隔计时器的地方使用它。@rek2:你不应该使用时间。After作为睡眠,也不应该在这里使用睡眠。你最初使用股票代码的想法是正确的,你只是想阻止它。我只是在我的玩具示例中使用了sleep,我绝对不建议在代码中添加sleep@rek2使用@JimB下面的方法。我不是指实际的睡眠调用,你使用的是时间。之后作为睡眠,并在应该使用间隔计时器的地方使用它。这个编译吗?我在操场上看到了这一点:不能在ticker type*time.ticker范围内进行编译吗?我在操场上看到了这一点:不能超过ticker type*time.ticker的范围