I would like to change my ticker interval dynamically.
I've written down an example to show you how I did. My use case is something else than an "accelerometer" but I hope that it gives you an idea.
http://play.golang.org/p/6ANFnoE6pA
package main
import (
"time"
"log"
"fmt"
)
func main() {
interval := float64(1000)
ticker := time.NewTicker(time.Duration(interval) * time.Millisecond)
go func(){
counter := 1.0
for range ticker.C {
log.Println("ticker accelerating to " + fmt.Sprint(interval/counter) + " ms")
ticker = time.NewTicker(time.Duration(interval/counter) * time.Millisecond)
counter++
}
log.Println("stopped")
}()
time.Sleep(5 * time.Second)
log.Println("stopping ticker")
ticker.Stop()
}
What is wrong is that the ticker will always "tick" every seconds and it doesn't accelerate... Any idea?
that why in go1.15 ticker.Reset
is created, you don't need to create a new ticker update the existing tickers duration with ticker.Reset("new duration")
, and now you will not have any cache issues
Go playground
package main
import (
"fmt"
"log"
"time"
)
func main() {
interval := float64(1000)
ticker := time.NewTicker(time.Duration(interval) * time.Millisecond)
go func(){
counter := 1.0
for range ticker.C {
log.Println("ticker accelerating to " + fmt.Sprint(interval/counter) + " ms")
ticker.Reset(time.Duration(interval/counter) * time.Millisecond)
counter++
}
log.Println("stopped")
}()
time.Sleep(5 * time.Second)
log.Println("stopping ticker")
ticker.Stop()
}
The reason your example have a cache issue is that when you reassign the ticker
variable with a *time.ticker
struct you just unlink the original *time.ticker
struct from the ticker
variable but the loop is still tide to the original ticker channel you need to reassin a new loop to the new time.ticker.c
Following the answer to @fzerorubigd but a little more complete.
As said before, we can't use the range
for this case, because the range
loop caches the variable to be lopped and then it can't be overwritten (example here: http://play.golang.org/p/yZvrgURz4o )
Then, we should use a for
-select
combination loop. Hereafter the working solution:
http://play.golang.org/p/3uJrAIhnTQ
package main
import (
"time"
"log"
"fmt"
)
func main() {
start_interval := float64(1000)
quit := make(chan bool)
go func(){
ticker := time.NewTicker(time.Duration(start_interval) * time.Millisecond)
counter := 1.0
for {
select {
case <-ticker.C:
log.Println("ticker accelerating to " + fmt.Sprint(start_interval/counter) + " ms")
ticker.Stop()
ticker = time.NewTicker(time.Duration(start_interval/counter) * time.Millisecond)
counter++
case <-quit:
ticker.Stop()
log.Println("..ticker stopped!")
return
}
}
}()
time.Sleep(5 * time.Second)
log.Println("stopping ticker...")
quit<-true
time.Sleep(500 * time.Millisecond) // just to see quit messages
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With