使用示例

执行后,输出结果为:

  1. v1
  2. 1
  3. true
  4. v1

过期控制

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/v2/os/gcache"
  5. "github.com/gogf/gf/v2/os/gctx"
  6. "time"
  7. )
  8. func main() {
  9. var (
  10. ctx = gctx.New()
  11. )
  12. // 当键名不存在时写入,设置过期时间1000毫秒
  13. _, err := gcache.SetIfNotExist(ctx, "k1", "v1", time.Second)
  14. if err != nil {
  15. panic(err)
  16. }
  17. // 打印当前的键名列表
  18. keys, err := gcache.Keys(ctx)
  19. if err != nil {
  20. panic(err)
  21. }
  22. // 打印当前的键值列表
  23. values, err := gcache.Values(ctx)
  24. if err != nil {
  25. panic(err)
  26. }
  27. fmt.Println(values)
  28. value, err := gcache.GetOrSet(ctx, "k2", "v2", 0)
  29. if err != nil {
  30. panic(err)
  31. }
  32. fmt.Println(value)
  33. // 打印当前的键值对
  34. data1, err := gcache.Data(ctx)
  35. if err != nil {
  36. panic(err)
  37. }
  38. fmt.Println(data1)
  39. // 等待1秒,以便k1:v1自动过期
  40. time.Sleep(time.Second)
  41. // 再次打印当前的键值对,发现k1:v1已经过期,只剩下k2:v2
  42. data2, err := gcache.Data(ctx)
  43. if err != nil {
  44. panic(err)
  45. }
  46. fmt.Println(data2)
  47. }

执行后,输出结果为:

需要注意的是,GetOrSetFunc的缓存方法参数f是在缓存的锁机制外执行,因此在f内部也可以嵌套调用GetOrSetFunc。但如果f的执行比较耗时,高并发的时候容易出现f被多次执行的情况(缓存设置只有第一个执行的f返回结果能够设置成功,其余的被抛弃掉)。而GetOrSetFuncLock的缓存方法f是在缓存的锁机制内执行,因此可以保证当缓存项不存在时只会执行一次f,但是缓存写锁的时间随着f方法的执行时间而定。

我们来看一个示例:

  1. package main
  2. "github.com/gogf/gf/v2/os/gcache"
  3. "github.com/gogf/gf/v2/os/gctx"
  4. "time"
  5. )
  6. func main() {
  7. var (
  8. ch = make(chan struct{}, 0)
  9. ctx = gctx.New()
  10. key = `key`
  11. value = `value`
  12. )
  13. for i := 0; i < 10; i++ {
  14. go func(index int) {
  15. <-ch
  16. _, err := gcache.GetOrSetFuncLock(ctx, key, func() (interface{}, error) {
  17. fmt.Println(index, "entered")
  18. return value, nil
  19. }, 0)
  20. if err != nil {
  21. panic(err)
  22. }
  23. }(i)
  24. }
  25. close(ch)
  26. time.Sleep(time.Second)
  27. }
  1. 9 entered

可以看到,多个goroutine同时调用GetOrSetFuncLock方法时,由于该方法有并发安全控制,因此最终只有一个goroutine的数值生成函数执行成功,成功之后其他goroutine拿到数据后则立即返回不再执行对应的数值生成函数。

LRU缓存淘汰控制

执行后,输出结果为:

  1. 10
  2. [2 3 5 6 7 0 1 4 8 9]
  3. 1
  4. 2
  5. [1 9]

性能测试

  1. CPU: Intel(R) Core(TM) i5-4460 CPU @ 3.20GHz

测试结果