ZBLOG

golang 实现对map中的key设置超时时间,超时后删除

Go语言中的map不支持直接设置键的超时时间,因此我们可以通过以下方法实现:

  1. 维护一个存储key超时时间的map,以及一个实际存储数据的map。

  2. 在插入数据时,同时将key和对应的超时时间存入第一个map中。

  3. 启动一个goroutine来定期遍历第一个map,删除超时的key,并在第二个map中也进行删除操作。

  4. 在查询数据时,先判断该key是否过期。如果已经过期,则从第二个map中删除并返回空值;否则返回正常的值。

下面是示例代码:

package main

import (
    "fmt"
    "sync"
    "time"
)

type TimeoutMap struct {
    m      map[string]interface{} // 存储实际数据
    expMap map[string]int64       // 存储key的超时时间
    mutex  sync.RWMutex           // 读写锁,保证并发安全
}

func NewTimeoutMap() *TimeoutMap {
    tm := &TimeoutMap{
        m:      make(map[string]interface{}),
        expMap: make(map[string]int64),
        mutex:  sync.RWMutex{},
    }
    go tm.cleanUp() // 启动清理过期键值对的协程
    return tm
}

// 设置键值对,并指定过期时间(秒)
func (tm *TimeoutMap) Set(key string, value interface{}, timeout int64) {
    tm.mutex.Lock()
    defer tm.mutex.Unlock()

    expireTime := time.Now().Unix() + timeout
    tm.m[key] = value
    tm.expMap[key] = expireTime
}

// 获取键值对,并判断是否过期。如果过期则删除并返回空值。
func (tm *TimeoutMap) Get(key string) interface{} {
    tm.mutex.RLock()
    defer tm.mutex.RUnlock()

    if val, ok := tm.m[key]; ok {
        if expireTime, ok := tm.expMap[key]; !ok || expireTime < time.Now().Unix() {
            delete(tm.m, key)
            delete(tm.expMap, key)
            return nil
        } else {
            return val
        }
    } else {
        return nil
    }
}

// 清理过期键值对的协程
func (tm *TimeoutMap) cleanUp() {
    for {
        <-time.After(1 * time.Second) // 每秒检查一次

        now := time.Now().Unix()
        keysToDelete := []string{}

        tm.mutex.Lock()
        for key, expTime := range tm.expMap {
            if expTime < now { // 如果已经过期,则记录需要删除的key
                keysToDelete = append(keysToDelete, key)
            }
        }

        // 删除需要删除的key
        for _, key := range keysToDelete {
            delete(tm.m, key)
            delete(tm.expMap, key)
        }
        tm.mutex.Unlock()
    }
}

func main() {
    m := NewTimeoutMap()

    m.Set("key1", "value1", 3) // 设置超时时间为3秒

    fmt.Println(m.Get("key1")) // 输出"value1"

    time.Sleep(4 * time.Second)

    fmt.Println(m.Get("key1")) // 输出"<nil>"
}

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=4750

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?