实现
This commit is contained in:
108
cache.go
Normal file
108
cache.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Cache[K comparable, V any] struct {
|
||||
mu sync.RWMutex
|
||||
data map[K]*Data[V] // 数据
|
||||
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: make(map[K]*Data[V]),
|
||||
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()
|
||||
var dKeys []K
|
||||
|
||||
c.mu.RLock()
|
||||
for k, v := range c.data {
|
||||
if v.End.IsZero() && v.End.Before(now) {
|
||||
dKeys = append(dKeys, k)
|
||||
}
|
||||
}
|
||||
c.mu.RUnlock()
|
||||
|
||||
// 删除过期数据
|
||||
if len(dKeys) > 0 {
|
||||
c.mu.Lock()
|
||||
for _, k := range dKeys {
|
||||
if c.cDel != nil {
|
||||
c.cDel(k, *c.data[k])
|
||||
}
|
||||
delete(c.data, k)
|
||||
}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
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()
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user