ZBLOG

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

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

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

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

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

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

下面是示例代码:

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. "time"
  6. )
  7. type TimeoutMap struct {
  8. m map[string]interface{} // 存储实际数据
  9. expMap map[string]int64 // 存储key的超时时间
  10. mutex sync.RWMutex // 读写锁,保证并发安全
  11. }
  12. func NewTimeoutMap() *TimeoutMap {
  13. tm := &TimeoutMap{
  14. m: make(map[string]interface{}),
  15. expMap: make(map[string]int64),
  16. mutex: sync.RWMutex{},
  17. }
  18. go tm.cleanUp() // 启动清理过期键值对的协程
  19. return tm
  20. }
  21. // 设置键值对,并指定过期时间(秒)
  22. func (tm *TimeoutMap) Set(key string, value interface{}, timeout int64) {
  23. tm.mutex.Lock()
  24. defer tm.mutex.Unlock()
  25. expireTime := time.Now().Unix() + timeout
  26. tm.m[key] = value
  27. tm.expMap[key] = expireTime
  28. }
  29. // 获取键值对,并判断是否过期。如果过期则删除并返回空值。
  30. func (tm *TimeoutMap) Get(key string) interface{} {
  31. tm.mutex.RLock()
  32. defer tm.mutex.RUnlock()
  33. if val, ok := tm.m[key]; ok {
  34. if expireTime, ok := tm.expMap[key]; !ok || expireTime < time.Now().Unix() {
  35. delete(tm.m, key)
  36. delete(tm.expMap, key)
  37. return nil
  38. } else {
  39. return val
  40. }
  41. } else {
  42. return nil
  43. }
  44. }
  45. // 清理过期键值对的协程
  46. func (tm *TimeoutMap) cleanUp() {
  47. for {
  48. <-time.After(1 * time.Second) // 每秒检查一次
  49. now := time.Now().Unix()
  50. keysToDelete := []string{}
  51. tm.mutex.Lock()
  52. for key, expTime := range tm.expMap {
  53. if expTime < now { // 如果已经过期,则记录需要删除的key
  54. keysToDelete = append(keysToDelete, key)
  55. }
  56. }
  57. // 删除需要删除的key
  58. for _, key := range keysToDelete {
  59. delete(tm.m, key)
  60. delete(tm.expMap, key)
  61. }
  62. tm.mutex.Unlock()
  63. }
  64. }
  65. func main() {
  66. m := NewTimeoutMap()
  67. m.Set("key1", "value1", 3) // 设置超时时间为3秒
  68. fmt.Println(m.Get("key1")) // 输出"value1"
  69. time.Sleep(4 * time.Second)
  70. fmt.Println(m.Get("key1")) // 输出"<nil>"
  71. }

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?