diff --git a/ticker/ticker.go b/ticker/ticker.go new file mode 100644 index 0000000..2bd9197 --- /dev/null +++ b/ticker/ticker.go @@ -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) +} diff --git a/ticker/ticker_test.go b/ticker/ticker_test.go new file mode 100644 index 0000000..7750a80 --- /dev/null +++ b/ticker/ticker_test.go @@ -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) +}