sync_dict.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Author: simon (ynwdlxm@163.com)
  2. // Date: 2025/9/15 17:07
  3. // Desc: 线程安全的字典实现,基于 sync.Map
  4. package dict
  5. import (
  6. "math/rand"
  7. "sync"
  8. )
  9. // SyncDict 是基于 sync.Map 的线程安全字典实现
  10. // 实现了 Dict 接口的所有方法
  11. type SyncDict struct {
  12. m sync.Map
  13. }
  14. // Get 根据键获取值
  15. // 参数 key 要查找的键
  16. // 返回值 value 是与键关联的值,ok 表示键是否存在
  17. func (s *SyncDict) Get(key string) (any, bool) {
  18. return s.m.Load(key)
  19. }
  20. // Len 返回字典中键值对的数量
  21. // 通过遍历所有元素来计算长度
  22. func (s *SyncDict) Len() int {
  23. length := 0
  24. s.m.Range(func(key, value any) bool {
  25. length++
  26. return true
  27. })
  28. return length
  29. }
  30. // Put 插入或更新键值对
  31. // 参数 key 键
  32. // 参数 value 值
  33. // 返回值 result 表示操作结果:1表示新增,0表示更新
  34. func (s *SyncDict) Put(key string, value any) (result int) {
  35. _, loaded := s.m.LoadOrStore(key, value)
  36. if loaded {
  37. // 如果键已存在,则更新它
  38. s.m.Store(key, value)
  39. return 0 // 更新
  40. }
  41. return 1 // 新增
  42. }
  43. // PutIfAbsent 当键不存在时才插入键值对
  44. // 参数 key 键
  45. // 参数 value 值
  46. // 返回值 result 表示操作结果:1表示插入成功,0表示键已存在未插入
  47. func (s *SyncDict) PutIfAbsent(key string, value any) (result int) {
  48. _, loaded := s.m.LoadOrStore(key, value)
  49. if loaded {
  50. return 0 // 键已存在
  51. }
  52. return 1 // 插入成功
  53. }
  54. // PutIfExists 当键存在时才更新键值对
  55. // 参数 key 键
  56. // 参数 value 值
  57. // 返回值 result 表示操作结果:1表示更新成功,0表示键不存在未更新
  58. func (s *SyncDict) PutIfExists(key string, value any) (result int) {
  59. _, ok := s.m.Load(key)
  60. if ok {
  61. s.m.Store(key, value)
  62. return 1 // 更新成功
  63. }
  64. return 0 // 键不存在
  65. }
  66. // Remove 根据键删除键值对
  67. // 参数 key 要删除的键
  68. // 返回值 result 表示操作结果:1表示删除成功,0表示键不存在未删除
  69. func (s *SyncDict) Remove(key string) (result int) {
  70. _, ok := s.m.LoadAndDelete(key)
  71. if ok {
  72. return 1 // 删除成功
  73. }
  74. return 0 // 键不存在
  75. }
  76. // ForEach 遍历字典中的所有键值对
  77. // 参数 consumer 是处理每个键值对的函数,当consumer返回false时停止遍历
  78. func (s *SyncDict) ForEach(consumer Consumer) {
  79. s.m.Range(func(key, value any) bool {
  80. return consumer(key.(string), value)
  81. })
  82. }
  83. // Keys 返回字典中所有的键
  84. // 返回包含所有键的字符串切片
  85. func (s *SyncDict) Keys() []string {
  86. keys := make([]string, 0)
  87. s.m.Range(func(key, value any) bool {
  88. keys = append(keys, key.(string))
  89. return true
  90. })
  91. return keys
  92. }
  93. // RandomKeys 随机返回字典中的键,可能包含重复键
  94. // 参数 limit 限制返回键的数量
  95. func (s *SyncDict) RandomKeys(limit int) []string {
  96. keys := s.Keys()
  97. if len(keys) == 0 {
  98. return make([]string, limit)
  99. }
  100. result := make([]string, limit)
  101. for i := 0; i < limit; i++ {
  102. result[i] = keys[rand.Intn(len(keys))]
  103. }
  104. return result
  105. }
  106. // RandomDistinctKeys 随机返回字典中的不重复键
  107. // 参数 limit 限制返回键的数量
  108. func (s *SyncDict) RandomDistinctKeys(limit int) []string {
  109. keys := s.Keys()
  110. if len(keys) <= limit {
  111. return keys
  112. }
  113. // Fisher-Yates shuffle 算法的一部分,用于随机选择不重复的键
  114. result := make([]string, limit)
  115. for i := 0; i < limit; i++ {
  116. // 从剩余元素中随机选择一个
  117. j := i + rand.Intn(len(keys)-i)
  118. // 交换元素
  119. keys[i], keys[j] = keys[j], keys[i]
  120. result[i] = keys[i]
  121. }
  122. return result
  123. }
  124. // Clear 清空字典中的所有键值对
  125. // 通过创建一个新的空 SyncDict 来实现清空操作
  126. func (s *SyncDict) Clear() {
  127. *s = *NewSyncDict()
  128. }
  129. // NewSyncDict 创建并返回一个新的 SyncDict 实例
  130. func NewSyncDict() *SyncDict {
  131. return &SyncDict{}
  132. }