Github:https://github.com/bluele/gcache
为 Golang 打造的缓存库。 它支持可预期的 Cache,LFU,LRU 和 ARC。
Goroutine 安全
$ go get github.com/bluele/gcache
手工配置键值对
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)
}
手动设置具有过期时间的键值对。
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)
}
自动负载值
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)
}
自动加载值与到期时间
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")
}
}
Least-Frequently Used (LFU)
使用次数最少,首先丢弃最不常用的缓存。
func main() {
// size: 10
gc := gcache.New(10).
LFU().
Build()
gc.Set("key", "value")
}
Least Recently Used (LRU)
最近最少使用,最先丢弃最近最少使用的物品。
func main() {
// size: 10
gc := gcache.New(10).
LRU().
Build()
gc.Set("key", "value")
}
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")
}
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()
}
被驱逐的处理程序
事件处理程序,用于驱逐条目。驱逐条目时执行该函数。
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)
}
}
添加处理程序
事件处理程序,用于添加条目。添加条目时执行该函数。
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)
}
}