54 lines
1.3 KiB
Go
54 lines
1.3 KiB
Go
// Timeup是一个限制某个值的重复频率的工具
|
|
// 通过内部计时器实现限制同一个值的访问频率不超过指定时间间隔
|
|
package check
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// TimeLimit结构体包含需要限频的映射表,以及时间间隔
|
|
// 使用sync.Mutex保证对字典的线程安全访问
|
|
type TimeLimit[T comparable] struct {
|
|
mu sync.Mutex
|
|
dict map[T]struct{}
|
|
dur time.Duration
|
|
}
|
|
|
|
// NewTimeLimit构造函数,接收限频的时间间隔
|
|
// 并初始化内部字典和间隔字段
|
|
func NewTimeLimit[T comparable](dur time.Duration) *TimeLimit[T] {
|
|
return &TimeLimit[T]{
|
|
dict: make(map[T]struct{}),
|
|
dur: dur,
|
|
}
|
|
}
|
|
|
|
// WithTime方法用于更新限频的时间间隔
|
|
func (tup *TimeLimit[T]) WithTime(dur time.Duration) *TimeLimit[T] {
|
|
tup.mu.Lock()
|
|
defer tup.mu.Unlock()
|
|
tup.dur = dur
|
|
return tup
|
|
}
|
|
|
|
// Is方法检查传入值是否是一个新的值
|
|
// 首先会查询字典,如果存在则表示在间隔内已经访问过
|
|
// 否则将其添加到字典,并启动一个定时器在间隔后删除
|
|
// 返回true表示新值,false表示重复值
|
|
func (tup *TimeLimit[T]) Is(v T) bool {
|
|
tup.mu.Lock()
|
|
defer tup.mu.Unlock()
|
|
|
|
if _, ok := tup.dict[v]; ok {
|
|
return false
|
|
}
|
|
tup.dict[v] = struct{}{}
|
|
time.AfterFunc(tup.dur, func() {
|
|
tup.mu.Lock()
|
|
defer tup.mu.Unlock()
|
|
delete(tup.dict, v)
|
|
})
|
|
return true
|
|
}
|