zl程序教程

您现在的位置是:首页 >  其他

当前栏目

Go --- GCache缓存官方例子

2023-03-14 22:41:38 时间

Github:https://github.com/bluele/gcache

介绍

为 Golang 打造的缓存库。 它支持可预期的 Cache,LFU,LRU 和 ARC。

功能

  • 支持可预见的 Cache,LFU,LRU 和 ARC。
  • Goroutine 安全
  • 支持驱逐,清除和添加条目的事件处理程序。 (可选)
  • 如果缓存不存在,则自动加载缓存。 (可选)

安装

$ go get github.com/bluele/gcache
• 1

例子

  1. 手工配置键值对
package main
import (
   "fmt"
   "github.com/bluele/gcache"
)
func main() {
     // size为设置的每小时的字节数,单位是 MB
    // func New(size int) *CacheBuilder {
    //  return &CacheBuilder{
    //      clock: NewRealClock(),
    //      tp:    TYPE_SIMPLE,
    //      size:  size,
    //  }
    // }
   gc := gcache.New(20).
      LRU().
      Build()
   gc.Set("key", "你好")
   value, err := gc.Get("key")
   if err != nil {
      panic(err)
   }
   fmt.Println("Get:", value)
}
  1. 手动设置具有过期时间的键值对。
package main
import (
   "fmt"
   "github.com/bluele/gcache"
   "log"
   "time"
)
func main() {
   gc := gcache.New(20).
      LRU().
      Build()
   // 设置并带上过期时间
   gc.SetWithExpire("key", "ok", time.Second*10)
   value, _ := gc.Get("key")
   fmt.Println("Get:", value)
   // 等待值过期
   time.Sleep(time.Second*10)
   value, err := gc.Get("key")
   if err != nil {
      // Key not found.
      log.Println(err)
   }
   fmt.Println("Get:", value)
}
  1. 自动负载值
package main
import (
   "fmt"
   "github.com/bluele/gcache"
   "time"
)
func main() {
   gc := gcache.New(20).
      LRU().
      // loaderFunc:当缓存值过期时,使用此函数创建一个新值。
      LoaderFunc(func(key interface{}) (interface{}, error) {
         return "默认值", nil
      }).
      Build()
   value1, err := gc.Get("张三")
   if err != nil {
      panic(err)
   }
   value2, err := gc.Get("李四")
   if err != nil {
      panic(err)
   }
   fmt.Println("张三:", value1)
   fmt.Println("李四:", value2)
   _ = gc.SetWithExpire("王五", "虽然可以修改", 5*time.Second)
   value3, err := gc.Get("王五")
   if err != nil {
      panic(err)
   }
   fmt.Print("王五:", value3)
   time.Sleep(5*time.Second)
   value4, err := gc.Get("王五")
   if err != nil {
      panic(err)
   }
   fmt.Println(" 但是过期了重新赋为", value4)
}
  1. 自动加载值与到期时间
package main
import (
   "fmt"
   "time"
   "github.com/bluele/gcache"
)
func main() {
   var evictCounter, loaderCounter, purgeCounter int
   gc := gcache.New(20).
      LRU().
      // loaderExpireFunc:当缓存值过期时,使用此函数创建一个新值。
      // 如果*time.Duration返回nil而不是时间。loaderExpireFunc比value的持续时间永远不会过期。
      LoaderExpireFunc(func(key interface{}) (interface{}, *time.Duration, error) {
         loaderCounter++
         expire := 1 * time.Second
         // return interface{}, *time.Duration, error
         return "好好吃饭", &expire, nil
      }).
      // 如果有新的键和老的键冲突了,那么将会驱逐老的键
      EvictedFunc(func(key, value interface{}) {
         evictCounter++
         fmt.Println("evicted key:", key)
      }).
      PurgeVisitorFunc(func(key, value interface{}) {
         purgeCounter++
      fmt.Println("purged key:", key)
      }).
      Build()
   value, err := gc.Get("规律作息")
   if err != nil {
      panic(err)
   }
   fmt.Println("规律作息:", value)
   time.Sleep(1 * time.Second)
   value, err = gc.Get("规律作息")
   if err != nil {
      panic(err)
   }
   fmt.Println("规律作息:", value)
   // 手动配置键值对
   _ = gc.Set("麦", "当")
   value, err = gc.Get("麦")
   if err != nil {
      panic(err)
   }
   fmt.Println("麦:", value)
   // 清理缓存
   gc.Purge()
   // 因为我们手动配置了键值对,所以将会执行下方的panic
   if loaderCounter != evictCounter+purgeCounter {
      fmt.Println("负载计数器:",loaderCounter)
      fmt.Println("驱逐计数器:",evictCounter)
      fmt.Println("清除计数器:",purgeCounter)
      panic("bad")
   }
}

缓存算法说明

  1. Least-Frequently Used (LFU)
    使用次数最少,首先丢弃最不常用的缓存。
func main() {
  // size: 10
  gc := gcache.New(10).
    LFU().
    Build()
  gc.Set("key", "value")
}
  1. Least Recently Used (LRU)
    最近最少使用,最先丢弃最近最少使用的物品。
func main() {
  // size: 10
  gc := gcache.New(10).
    LRU().
    Build()
  gc.Set("key", "value")
}
  1. daptive Replacement Cache (ARC)
    自适应替换缓存,不断平衡LRU和LFU,提高组合效果。
    详细情况参考: http://en.wikipedia.org/wiki/Adaptive_replacement_cache
func main() {
  gc := gcache.New(10).
    ARC().
    Build()
  gc.Set("key", "value")
}
  1. SimpleCache (Default)
    SimpleCache没有明确的退出缓存优先级。它取决于键-值映射顺序。
func main() {
  gc := gcache.New(10).Build()
  gc.Set("key", "value")
  v, err := gc.Get("key")
  if err != nil {
    panic(err)
  }
}

加载缓存

如果指定了LoaderFunc,值将由缓存自动加载,并存储在缓存中,直到驱逐或手动失效。

func main() {
  gc := gcache.New(10).
    LRU().
    LoaderFunc(func(key interface{}) (interface{}, error) {
      return "value", nil
    }).
    Build()
  v, _ := gc.Get("key")
  fmt.Println(v)
}

GCache协调缓存填充,使整个复制的进程集中的一个进程中只有一个加载填充缓存,然后将加载的值复用给所有调用者。

为缓存设置过期时间

func main() {
  // LRU 缓存, 大小:10MB, 过期时间: 一小时后
  gc := gcache.New(10).
    LRU().
    Expiration(time.Hour).
    Build()
}

事件处理程序

  1. 被驱逐的处理程序
    事件处理程序,用于驱逐条目。驱逐条目时执行该函数。
func main() {
  gc := gcache.New(2).
    EvictedFunc(func(key, value interface{}) {
      fmt.Println("evicted key:", key)
    }).
    Build()
  for i := 0; i < 3; i++ {
    gc.Set(i, i*i)
  }
}
  1. 添加处理程序
    事件处理程序,用于添加条目。添加条目时执行该函数。
func main() {
  gc := gcache.New(2).
    AddedFunc(func(key, value interface{}) {
      fmt.Println("added key:", key)
    }).
    Build()
  for i := 0; i < 3; i++ {
    gc.Set(i, i*i)
  }
}