I want to implement a status script on my server and I’m looking for the best way to run the function every second.
I came up with the following code but I don’t know if it’s the best way:
package main
import (
"fmt"
"time"
)
func main() {
iteration := 0
timer := time.NewTicker(time.Millisecond * 1000)
go func() {
for t := range timer.C {
fmt.Println("Connect to local application and check status at", t)
iteration++
if iteration == 10 {
fmt.Println("Connect to main status server.")
iteration = 0
}
}
}()
<-make(chan struct{})
return
}
package main
import (
"fmt"
"time"
)
func main() {
go func() {
iteration := 0
for t := range time.Tick(time.Second) {
fmt.Println("Connect to local application and check status at", t)
iteration++
if iteration == 10 {
fmt.Println("Connect to main status server.")
iteration = 0
}
}
}()
select {}
}
Moving iteration to the goroutine prevents it from escaping to the heap. This can be checked by building with go build -gcflags="-m" main.go. Leaving iteration in main()'s scope also gives the potential for a race condition.
Since the ticker was only used as the for loop’s range, I moved it there. time.Tick is a convenience function around time.NewTicker that only returns the channel. Note that with this new setup there is no way to shut the ticker down. That is probably not a problem because the server should always report its health.
I used time.Second instead of basing on milliseconds because it is easier to read.
I used select{} instead of <-make(chan struct{}) because it is more efficient. It basically tells the scheduler that the function will block forever. Creating a channel and then reading from it creates a condition in which the function could continue that must then be checked.
There is no reason to return at the end of a function that does not return anything. Executing to the end of the function body has the same effect. Also, the return would never be encountered because nothing could be sent to the channel and so nothing could be read from it, blocking forever.