1

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
        }

    }
icza
  • 389,944
  • 63
  • 907
  • 827
Blankman
  • 259,732
  • 324
  • 769
  • 1,199

1 Answers1

2

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...
        }()
    }
}
icza
  • 389,944
  • 63
  • 907
  • 827