Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegantly run the body of a Ticker before the first interval?

Tags:

for-loop

go

timer

New to Go, I've implemented a small Ticker to poll an API at a given interval:

func Poll() <-chan map[uint8]Data {
    json := make(chan map[uint8]Data)

    user, pass, endpoint := credentials.Get()

    ticker := time.NewTicker(90 * time.Second)

    client := &http.Client{}
    req, _ := http.NewRequest("GET", endpoint, nil)
    req.SetBasicAuth(user, pass)

    go func() {
        for range ticker.C {
            resp, _ := client.Do(req)
            bodyText, _ := ioutil.ReadAll(resp.Body)
            json <- extract(string(bodyText))
        }
    }()

    return json
}

Obviously this waits until the first whole interval has elapsed before calling the API for the first poll; that's not desirable.

This naive (but working) solution seems...weird:

go func() {
    resp, _ := client.Do(req)
    bodyText, _ := ioutil.ReadAll(resp.Body)
    json <- extract(string(bodyText))
}()

go func() {
    for range ticker.C {
        resp, _ := client.Do(req)
        bodyText, _ := ioutil.ReadAll(resp.Body)
        json <- extract(string(bodyText))
    }
}()

Is there a better or more more idiomatic Go way to accomplish this?

like image 978
msanford Avatar asked Mar 04 '23 13:03

msanford


1 Answers

I've done it like this in the past:

for ; true; <-ticker.C {
    resp, _ := client.Do(req)
    bodyText, _ := ioutil.ReadAll(resp.Body)
    json <- extract(string(bodyText))
}

For example:

t := time.NewTicker(2 * time.Second)
now := time.Now()
for ; true; <-t.C {
    fmt.Println(time.Since(now))
}

https://play.golang.org/p/1wz99kzZZ92

like image 199
dave Avatar answered Mar 09 '23 05:03

dave