dynamically change ticker interval
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
}
As Nipun Talukdar mentioned, the "for" capture the channel and use the same reference for iterate. it fixed if you use it like this :
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 {
select {
case <-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()
}