当前位置: 首页 > article >正文

在 Go 中,如何实现一个带过期时间的字典映射

有些时候,应用系统用不上 redis,我们也可以用锁和 goroutine 实现一个带有过期时间的线程安全的字典。

这种字典的应用场景,比较倾向于数据规模较小,没有分布式要求。

下面是实现:

1、定义结构

type Item struct {  
    value    interface{}  
    expireAt int64  
}  
  
type TTLMap struct {  
    m  map[string]*Item  
    mu sync.Mutex  
}

字典的值是一个可以接收任何类型的 interface{}

2、定义行为

  
func NewTTLMap(size int) (m *TTLMap) {  
    m = &TTLMap{m: make(map[string]*Item, size)}  
    go func() {  
       for now := range time.Tick(time.Second) {  
          m.mu.Lock()  
          for k, v := range m.m {  
             if v.expireAt <= now.Unix() {  
                delete(m.m, k)  
             }  
          }  
          m.mu.Unlock()  
       }  
    }()  
    return  
}  
  
func (m *TTLMap) Set(key string, value interface{}, ttl int64) {  
    m.mu.Lock()  
    defer m.mu.Unlock()  
    m.m[key] = &Item{value: value, expireAt: time.Now().Unix() + ttl}  
}  
  
func (m *TTLMap) Get(key string) (v interface{}, ok bool) {  
    m.mu.Lock()  
    defer m.mu.Unlock()  
    if item, ok := m.m[key]; ok && item.expireAt > time.Now().Unix() {  
       return item.value, true  
    }  
    return nil, false  
}

NewTTLMap 函数用来初始化字典,然后使用 goroutine 开启新的轻量级线程,按照一定的频率从字典里删除项。

Get 函数用来获取字典的值,然后这里也判断一下过期时间,如果已经过期了,就不再返回了。

3、验证结果

func TestTTLMap(t *testing.T) {  
    m := NewTTLMap(10)  
    m.Set("hello", "world", 5)  
    for i := 0; i < 10; i++ {  
       time.Sleep(time.Second)  
       if v, ok := m.Get("hello"); ok {  
          t.Log(v)  
       } else {  
          t.Log("expired")  
       }  
    }  
}

输出结果:

=== RUN   TestTTLMap
    ttl_map_test.go:64: world
    ttl_map_test.go:64: world
    ttl_map_test.go:64: world
    ttl_map_test.go:64: world
    ttl_map_test.go:66: expired
    ttl_map_test.go:66: expired
    ttl_map_test.go:66: expired
    ttl_map_test.go:66: expired
    ttl_map_test.go:66: expired
    ttl_map_test.go:66: expired
--- PASS: TestTTLMap (10.00s)
PASS

每秒读取一次,由于过期时间是 5 秒,因此,5 秒之后就读取不到值了。

Over!


http://www.kler.cn/news/364063.html

相关文章:

  • 京准电钟HR-901GB双GPS北斗卫星时钟服务器
  • OpenCV和HALCON
  • K8S部署
  • 讲个故事:关于一次接口性能优化的心里路程
  • [分享] SQL在线编辑工具(好用)
  • 为什么k8s不支持docker-kubernetes
  • colcon构建ros2功能包时,出现exited with code 2报错的解决方案(bug)
  • 构建后端为etcd的CoreDNS的容器集群(五)、coredns对接etcd测试
  • 延迟队列实现及其原理详解
  • GD32E50x 三路CANFD配置
  • 在Milvus中管理Schema
  • 产品如何实现3D展示?具体步骤如下
  • Prompt-Tuning方法学习
  • 龙蟠科技业绩压力显著:资产负债率持续攀升,产能利用率也不乐观
  • YOLO11改进|卷积篇|引入大感受野小波卷积WTConv
  • 等保测评:网络安全等级保护测评的主要目的与核心价值
  • 软件设计师:软件工程
  • 【升华】一文从0到1到实际性应用大语言模型(LLM)
  • leetcode动态规划(十九)-完全平方数
  • 前端实现监控埋点
  • Linux——进程基础
  • 智联招聘×Milvus:向量召回技术提升招聘匹配效率
  • 华为配置 之 远程管理配置
  • 在pycharm中使用sqllite
  • 通过使用Visual Studio将你的程序一键发布到Docker
  • JavaWeb合集15-线程局部变量ThreadLocal