I seen tons of questions with responses on how to periodically run a function. The problem? They all lock the program from moving on.
What I need?
I have a websocket and I have a for {}
that keeps reading for msg's and now and every 10 secs I need to run a call to the heartbeat function, with out interrupting the program or stop reading the chat.
I am thinking in using some approaches but none of them seem clean/nice using channels, but I think someone more experienced may have a good and simpler approach to this.
I was using something like this but it never gets to the end of the function to return what I need for the program to continue.
timerCh := time.Tick(time.Duration(10) * time.Second)
for range timerCh {
go Heartbeat(ws)
}
return ws
I am looking for a way to be able to call Heartbeat every 10 secs with out:
Some context, This is for a bridge chat, so I open a websocket, keep reading from this, and only sent to the other chat when is a chat msg, in the mean time I need to sent a heartbeat with out locking this. What do I have now? now it all works, but after 30 secs or so my websocket closes:
2020/07/01 20:59:09 Error read: websocket: close 1000 (normal)
EDIT: Go with @JimB's answer! This was just meant to show that the timer should be managed outside of the main
goroutine.
Your heartbeat function should manage its own timer. Something like this should work:
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!")
}
}
This example will print from main
every 3 seconds and from heartbeat every 10
and will terminate after 30 seconds.