增加立即执行的定时器示例

This commit is contained in:
fantasticbin 2024-11-20 14:35:48 +08:00
parent 310206ad68
commit 9c8b64eaf3
2 changed files with 91 additions and 0 deletions

43
ticker/ticker.go Normal file
View File

@ -0,0 +1,43 @@
package ticker
import "time"
type Ticker struct {
C chan time.Time
ticker *time.Ticker
close chan struct{}
}
func NewTicker(d time.Duration) *Ticker {
return &Ticker{
C: make(chan time.Time, 1),
ticker: time.NewTicker(d),
close: make(chan struct{}),
}
}
func (t *Ticker) Start() {
// 首次直接触发
t.C <- time.Now()
go func() {
for {
select {
case <-t.close:
// 关闭时停止goroutine
return
case tc := <-t.ticker.C:
// 把go原生定时器 push 的时间推送到我们定义的 time channel 中
t.C <- tc
}
}
}()
}
func (t *Ticker) Reset(d time.Duration) {
t.ticker.Reset(d)
}
func (t *Ticker) Stop() {
t.ticker.Stop()
close(t.close)
}

48
ticker/ticker_test.go Normal file
View File

@ -0,0 +1,48 @@
package ticker
import (
"github.com/stretchr/testify/assert"
"testing"
"time"
)
func TestTicker(t *testing.T) {
now := time.Now()
// 记录初始时间
data := []int64{
now.Unix(),
}
expected := []int64{
now.Unix(),
}
// 预期每隔一秒收到一个信号
for i := 0; i < 3; i++ {
expected = append(expected, now.Add(time.Duration(i)*time.Second).Unix())
}
done := make(chan struct{})
ticker := NewTicker(time.Second)
ticker.Start()
go func() {
for {
select {
case <-done:
return
case t := <-ticker.C:
data = append(data, t.Unix())
}
}
}()
go func() {
// 设置成3秒有时候会有误差
time.Sleep(2500 * time.Millisecond)
ticker.Stop()
close(done)
}()
time.Sleep(3 * time.Second)
assert.Equal(t, expected, data)
}