So my application relies on a goroutine that polls every x seconds.
func main() {
// ...
go p.StartPoller();
}
What are some tips to make sure this poller is always running?
I'm just weary of things maybe because I don't understand fully the concept of error trapping in go. Since errors are values, and assuming I don't or any of the libraries I use call panic(), and no null pointer references or array out of bounds any code inside of this goroutine should not crash the goroutine correct?
func (p *Poller) StartPoller() {
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
for {
<-ticker.C
// code here
}
}
You are right, the code you posted should never panic and hence "crash" the goroutine.
As a best practice, to ensure the // code here
also doesn't do that, "wrap" it in a function (anonymous or named one), and use recover()
(deferred!) in that. This will ensure that the polling task will also never "crash" the polling scheduler.
Something like this:
func (p *Poller) StartPoller() {
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
for {
<-ticker.C
func() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered: %v", r)
}
}()
// code here
// If this would panic, it will be recovered...
}()
}
}
And even if the poller is to be always running, I would still add a "shutdown" channel to it, giving the possibility of graceful termination:
func (p *Poller) StartPoller(shutdown <-chan struct{}) {
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
case <-shutdown:
return
}
func() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered: %v", r)
}
}()
// code here
// If this would panic, it will be recovered...
}()
}
}