Files
cache/cache.go
2025-02-21 08:42:56 +08:00

97 lines
2.1 KiB
Go

package cache
import (
"fmt"
"strconv"
"sync"
"time"
)
type Cache[K comparable, V any] struct {
mu sync.RWMutex
data sync.Map // 数据
cSet func(K, Data[V]) // 设置数据回调
cGet func(K, Data[V]) // 获取数据回调
cGetData func(K, Data[V]) // 获取数据内容回调
cGetTTL func(K, Data[V]) // 获取数据剩余时间回调
cDel func(K, Data[V]) // 删除数据回调
cUpData func(K, Data[V]) // 更新数据内容回调
cUpTTL func(K, Data[V]) // 更新数据剩余时间回调
fatal func(error) // 致命错误执行的内容
gc func() // 自动清理过期数据
persist func() // 持久化数据
is64Bit bool // 是否为64位系统
}
type Data[V any] struct {
End time.Time // 过期时间 v.End.IsZero()=true表示永不过期
Val V // 数据
}
// NewCache 创建一个新的缓存实例
// K: 键的类型(可比较) V: 值的类型(允许any)
func NewCache[K comparable, V any]() *Cache[K, V] {
defFunc := func(k K, d Data[V]) {}
c := &Cache[K, V]{
data: sync.Map{},
cSet: defFunc,
cGet: defFunc,
cGetData: defFunc,
cGetTTL: defFunc,
cDel: defFunc,
cUpData: defFunc,
cUpTTL: defFunc,
fatal: func(err error) { fmt.Println(err) },
}
c.gc = c.collection()
c.is64Bit = strconv.IntSize == 64
return c
}
// 自动清理过期数据
func (c *Cache[K, V]) collection() func() {
ticker := time.NewTicker(time.Second)
stopChan := make(chan struct{})
go func() {
for {
select {
case <-stopChan:
return
case <-ticker.C:
now := time.Now()
c.data.Range(func(key, value any) bool {
if v, ok := value.(*Data[V]); ok {
if !v.End.IsZero() && v.End.Before(now) {
c.data.Delete(key)
}
}
return true
})
}
}
}()
return func() {
ticker.Stop()
stopChan <- struct{}{}
}
}
func (c *Cache[K, V]) SetFatalFunc(f func(error)) {
c.mu.Lock()
defer c.mu.Unlock()
c.fatal = f
}
// Destroy 销毁缓存实例
// 关闭缓存实例
func (c *Cache[K, V]) Destroy() {
c.gc()
if c.persist != nil {
c.persist()
}
c.data.Clear()
return
}