package main import ( "fmt" "strings" "time" ) type TickPrinter struct { Message chan func() string msg func() string lastLen int Interval time.Duration stop chan struct{} flush chan struct{} } func NewTickPrinter(interval time.Duration) *TickPrinter { return &TickPrinter{ Message: make(chan func() string), msg: func() string { return time.Now().Format("15:04:05") }, stop: make(chan struct{}), flush: make(chan struct{}), Interval: interval, } } func (t *TickPrinter) Start() { ticker := time.NewTicker(t.Interval) for { select { case <-t.flush: fmt.Printf("\n") t.Print() case <-ticker.C: t.Print() case msg := <-t.Message: t.msg = msg case <-t.stop: return } } } func (t *TickPrinter) Stop() { close(t.stop) time.Sleep(t.Interval) fmt.Printf("\n") } func (t *TickPrinter) Flush() { t.flush <- struct{}{} } func (t *TickPrinter) Print() { fmt.Printf("\r%s", strings.Repeat(" ", t.lastLen)) msg := t.msg() l := len(msg) if len(msg) < t.lastLen { msg += strings.Repeat(" ", t.lastLen-len(msg)) } t.lastLen = l fmt.Printf("\r%s", msg) }