Go语言中的map不支持直接设置键的超时时间,因此我们可以通过以下方法实现:
维护一个存储key超时时间的map,以及一个实际存储数据的map。
在插入数据时,同时将key和对应的超时时间存入第一个map中。
启动一个goroutine来定期遍历第一个map,删除超时的key,并在第二个map中也进行删除操作。
在查询数据时,先判断该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>"
}
                                    

        
        
        
        
        
        
        
        
        
                
                
                
                
                
                
                