cache.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. package service
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/gogf/gcache-adapter/adapter"
  6. "github.com/gogf/gf/crypto/gmd5"
  7. "github.com/gogf/gf/encoding/gjson"
  8. "github.com/gogf/gf/frame/g"
  9. "github.com/gogf/gf/os/gcache"
  10. "github.com/gogf/gf/util/gconv"
  11. "reflect"
  12. "sync"
  13. "time"
  14. )
  15. type cache struct {
  16. }
  17. type cacheTagService struct {
  18. tagKey interface{}
  19. cache *gcache.Cache
  20. tagSetMux *sync.Mutex
  21. }
  22. var (
  23. Cache = new(cache)
  24. userRedis = g.Cfg().GetBool("redis.open")
  25. gChe = gcache.New()
  26. )
  27. func (s *cache) New() *cacheTagService {
  28. gChe.Ctx(context.Background())
  29. if userRedis {
  30. adapter := adapter.NewRedis(g.Redis())
  31. gChe.SetAdapter(adapter)
  32. }
  33. return &cacheTagService{
  34. cache: gChe,
  35. tagSetMux: new(sync.Mutex),
  36. }
  37. }
  38. //设置tag缓存的keys
  39. func (c *cacheTagService) cacheTagKey(key interface{}, tag interface{}) {
  40. c.setTagKey(tag)
  41. if c.tagKey != nil {
  42. tagValue := []interface{}{key}
  43. value, _ := c.cache.Get(c.tagKey)
  44. if value != nil {
  45. var keyValue []interface{}
  46. //若是字符串
  47. if kStr, ok := value.(string); ok {
  48. js, err := gjson.DecodeToJson(kStr)
  49. if err != nil {
  50. g.Log().Error(err)
  51. return
  52. }
  53. keyValue = gconv.SliceAny(js.Value())
  54. } else {
  55. keyValue = gconv.SliceAny(value)
  56. }
  57. for _, v := range keyValue {
  58. if !reflect.DeepEqual(key, v) {
  59. tagValue = append(tagValue, v)
  60. }
  61. }
  62. }
  63. c.cache.Set(c.tagKey, tagValue, 0)
  64. }
  65. }
  66. //获取带标签的键名
  67. func (c *cacheTagService) setTagKey(tag interface{}) {
  68. if tag != nil {
  69. c.tagKey = interface{}(fmt.Sprintf("cache_tag_%s", gmd5.MustEncryptString(gconv.String(tag))))
  70. }
  71. }
  72. // Set sets cache with <tagKey>-<value> pair, which is expired after <duration>.
  73. // It does not expire if <duration> <= 0.
  74. func (c *cacheTagService) Set(key interface{}, value interface{}, duration time.Duration, tag ...interface{}) {
  75. c.tagSetMux.Lock()
  76. if len(tag) > 0 {
  77. c.cacheTagKey(key, tag[0])
  78. }
  79. err := c.cache.Set(key, value, duration)
  80. if err != nil {
  81. g.Log().Error(err)
  82. }
  83. c.tagSetMux.Unlock()
  84. }
  85. // SetIfNotExist sets cache with <tagKey>-<value> pair if <tagKey> does not exist in the cache,
  86. // which is expired after <duration>. It does not expire if <duration> <= 0.
  87. func (c *cacheTagService) SetIfNotExist(key interface{}, value interface{}, duration time.Duration, tag interface{}) bool {
  88. c.tagSetMux.Lock()
  89. defer c.tagSetMux.Unlock()
  90. c.cacheTagKey(key, tag)
  91. v, _ := c.cache.SetIfNotExist(key, value, duration)
  92. return v
  93. }
  94. // Sets batch sets cache with tagKey-value pairs by <data>, which is expired after <duration>.
  95. //
  96. // It does not expire if <duration> <= 0.
  97. func (c *cacheTagService) Sets(data map[interface{}]interface{}, duration time.Duration, tag interface{}) {
  98. c.tagSetMux.Lock()
  99. if tag != nil {
  100. for k, _ := range data {
  101. c.cacheTagKey(k, tag)
  102. }
  103. c.cache.Sets(data, duration)
  104. } else {
  105. c.cache.Sets(data, duration)
  106. }
  107. c.tagSetMux.Unlock()
  108. }
  109. // Get returns the value of <tagKey>.
  110. // It returns nil if it does not exist or its value is nil.
  111. func (c *cacheTagService) Get(key interface{}) interface{} {
  112. v, err := c.cache.Get(key)
  113. if err != nil {
  114. g.Log().Error(err)
  115. }
  116. return v
  117. }
  118. // GetOrSet returns the value of <tagKey>,
  119. // or sets <tagKey>-<value> pair and returns <value> if <tagKey> does not exist in the cache.
  120. // The tagKey-value pair expires after <duration>.
  121. //
  122. // It does not expire if <duration> <= 0.
  123. func (c *cacheTagService) GetOrSet(key interface{}, value interface{}, duration time.Duration, tag interface{}) interface{} {
  124. c.tagSetMux.Lock()
  125. defer c.tagSetMux.Unlock()
  126. c.cacheTagKey(key, tag)
  127. v, _ := c.cache.GetOrSet(key, value, duration)
  128. return v
  129. }
  130. // GetOrSetFunc returns the value of <tagKey>, or sets <tagKey> with result of function <f>
  131. // and returns its result if <tagKey> does not exist in the cache. The tagKey-value pair expires
  132. // after <duration>. It does not expire if <duration> <= 0.
  133. func (c *cacheTagService) GetOrSetFunc(key interface{}, f func() (interface{}, error), duration time.Duration, tag interface{}) interface{} {
  134. c.tagSetMux.Lock()
  135. defer c.tagSetMux.Unlock()
  136. c.cacheTagKey(key, tag)
  137. v, _ := c.cache.GetOrSetFunc(key, f, duration)
  138. return v
  139. }
  140. // GetOrSetFuncLock returns the value of <tagKey>, or sets <tagKey> with result of function <f>
  141. // and returns its result if <tagKey> does not exist in the cache. The tagKey-value pair expires
  142. // after <duration>. It does not expire if <duration> <= 0.
  143. //
  144. // Note that the function <f> is executed within writing mutex lock.
  145. func (c *cacheTagService) GetOrSetFuncLock(key interface{}, f func() (interface{}, error), duration time.Duration, tag interface{}) interface{} {
  146. c.tagSetMux.Lock()
  147. defer c.tagSetMux.Unlock()
  148. c.cacheTagKey(key, tag)
  149. v, _ := c.cache.GetOrSetFuncLock(key, f, duration)
  150. return v
  151. }
  152. // Contains returns true if <tagKey> exists in the cache, or else returns false.
  153. func (c *cacheTagService) Contains(key interface{}) bool {
  154. v, _ := c.cache.Contains(key)
  155. return v
  156. }
  157. // Remove deletes the <tagKey> in the cache, and returns its value.
  158. func (c *cacheTagService) Remove(key interface{}) interface{} {
  159. v, _ := c.cache.Remove(key)
  160. return v
  161. }
  162. // Removes deletes <keys> in the cache.
  163. func (c *cacheTagService) Removes(keys []interface{}) {
  164. c.cache.Remove(keys...)
  165. }
  166. // Remove deletes the <tag> in the cache, and returns its value.
  167. func (c *cacheTagService) RemoveByTag(tag interface{}) {
  168. c.tagSetMux.Lock()
  169. c.setTagKey(tag)
  170. //删除tagKey 对应的 key和值
  171. keys := c.Get(c.tagKey)
  172. if keys != nil {
  173. //如果是字符串
  174. if kStr, ok := keys.(string); ok {
  175. js, err := gjson.DecodeToJson(kStr)
  176. if err != nil {
  177. g.Log().Error(err)
  178. return
  179. }
  180. ks := gconv.SliceAny(js.Value())
  181. c.Removes(ks)
  182. } else {
  183. ks := gconv.SliceAny(keys)
  184. c.Removes(ks)
  185. }
  186. }
  187. c.Remove(c.tagKey)
  188. c.tagSetMux.Unlock()
  189. }
  190. // Removes deletes <tags> in the cache.
  191. func (c *cacheTagService) RemoveByTags(tag []interface{}) {
  192. for _, v := range tag {
  193. c.RemoveByTag(v)
  194. }
  195. }
  196. // Data returns a copy of all tagKey-value pairs in the cache as map type.
  197. func (c *cacheTagService) Data() map[interface{}]interface{} {
  198. v, _ := c.cache.Data()
  199. return v
  200. }
  201. // Keys returns all keys in the cache as slice.
  202. func (c *cacheTagService) Keys() []interface{} {
  203. v, _ := c.cache.Keys()
  204. return v
  205. }
  206. // KeyStrings returns all keys in the cache as string slice.
  207. func (c *cacheTagService) KeyStrings() []string {
  208. v, _ := c.cache.KeyStrings()
  209. return v
  210. }
  211. // Values returns all values in the cache as slice.
  212. func (c *cacheTagService) Values() []interface{} {
  213. v, _ := c.cache.Values()
  214. return v
  215. }
  216. // Size returns the size of the cache.
  217. func (c *cacheTagService) Size() int {
  218. v, _ := c.cache.Size()
  219. return v
  220. }