gcache

    使用方式:

    方法列表: godoc.org/github.com/johng-cn/gf/g/os/gcache

    1. func BatchRemove(keys []interface{})
    2. func BatchSet(data map[interface{}]interface{}, expire int)
    3. func Contains(key interface{}) bool
    4. func Get(key interface{}) interface{}
    5. func GetOrSet(key interface{}, value interface{}, expire int) interface{}
    6. func GetOrSetFunc(key interface{}, f func() interface{}, expire int) interface{}
    7. func GetOrSetFuncLock(key interface{}, f func() interface{}, expire int) interface{}
    8. func KeyStrings() []string
    9. func Keys() []interface{}
    10. func Remove(key interface{}) interface{}
    11. func Set(key interface{}, value interface{}, expire int)
    12. func SetIfNotExist(key interface{}, value interface{}, expire int) bool
    13. func Size() int
    14. func Values() []interface{}
    15. type Cache
    16. func New(lruCap ...int) *Cache
    17. func (c Cache) BatchRemove(keys []interface{})
    18. func (c Cache) BatchSet(data map[interface{}]interface{}, expire int)
    19. func (c *Cache) Clear()
    20. func (c Cache) Close()
    21. func (c Cache) Contains(key interface{}) bool
    22. func (c Cache) Get(key interface{}) interface{}
    23. func (c Cache) GetOrSet(key interface{}, value interface{}, expire int) interface{}
    24. func (c Cache) GetOrSetFunc(key interface{}, f func() interface{}, expire int) interface{}
    25. func (c Cache) GetOrSetFuncLock(key interface{}, f func() interface{}, expire int) interface{}
    26. func (c Cache) KeyStrings() []string
    27. func (c Cache) Keys() []interface{}
    28. func (c Cache) Remove(key interface{}) interface{}
    29. func (c Cache) Set(key interface{}, value interface{}, expire int)
    30. func (c Cache) SetIfNotExist(key interface{}, value interface{}, expire int) bool
    31. func (c Cache) Size() int
    32. func (c Cache) Values() []interface{}

    gcache可以使用New方法创建使用,并且也可以使用包方法使用。在通过包方法使用缓存功能时,其实操作gcache默认提供的一个gcache.Cache对象,具有全局性,因此在使用时注意全局键名的覆盖。

    另外需要注意的是,gcache的缓存时间单位为毫秒,在Set缓存变量时,缓存时间参数expire=0表示不过期,expire<0表示立即过期,expire>0表示超时过期。

    1. package main
    2. import (
    3. "gitee.com/johng/gf/g/os/gcache"
    4. "gitee.com/johng/gf/g"
    5. )
    6. func main() {
    7. // 创建一个缓存对象,当然也可以直接使用gcache包方法
    8. c := gcache.New()
    9. // 设置缓存,不过期
    10. c.Set("k1", "v1", 0)
    11. g.Dump(c.Get("k1"))
    12. // 缓存中是否存在指定键名
    13. g.Dump(c.Contains("k1"))
    14. // 删除并返回被删除的键值
    15. g.Dump(c.Remove("k1"))
    16. // 关闭缓存对象,让GC回收资源
    17. c.Close()
    18. }

    执行后,输出结果为:

    1. package main
    2. import (
    3. "gitee.com/johng/gf/g/os/gcache"
    4. "gitee.com/johng/gf/g"
    5. "time"
    6. )
    7. func main() {
    8. // 当键名不存在时写入,设置过期时间1000毫秒
    9. gcache.SetIfNotExist("k1", "k1", 1000)
    10. // 打印当前的键名列表
    11. g.Dump(gcache.Keys())
    12. // 打印当前的键名列表 []string 类型
    13. g.Dump(gcache.KeyStrings())
    14. // 获取指定键值,如果不存在时写入,并返回键值
    15. g.Dump(gcache.GetOrSet("k2", "v2", 0))
    16. // 打印当前的键值列表
    17. g.Dump(gcache.Values())
    18. // 等待1秒,以便k1:v1自动过期
    19. time.Sleep(time.Second)
    20. // 再次打印当前的键值列表,发现k1:v1已经过期,只剩下k2:v2
    21. g.Dump(gcache.Values())
    22. }

    执行后,输出结果为:

    1. [
    2. "k1"
    3. ]
    4. [
    5. "k1"
    6. ]
    7. "v2"
    8. [
    9. "k1",
    10. "v2"
    11. [
    12. "v2"
    13. ]

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

    我们来看一个在gf-home项目中使用GetOrSetFunc的示例,该示例遍历检索markdown文件进行字符串检索,并根据指定的搜索key缓存该结果值,因此多次搜索该key时,第一次执行目录遍历搜索,后续将直接使用缓存。

    1. package main
    2. import (
    3. "gitee.com/johng/gf/g/os/gcache"
    4. "time"
    5. "fmt"
    6. )
    7. func main() {
    8. // 设置LRU淘汰数量
    9. c := gcache.New(2)
    10. // 添加10个元素,不过期
    11. for i := 0; i < 10; i++ {
    12. c.Set(i, i, 0)
    13. }
    14. fmt.Println(c.Size())
    15. fmt.Println(c.Keys())
    16. // 读取键名1,保证该键名是优先保留
    17. fmt.Println(c.Get(1))
    18. // 等待一定时间后(默认10秒检查一次),元素会被按照从旧到新的顺序进行淘汰
    19. time.Sleep(10*time.Second)
    20. fmt.Println(c.Size())
    21. fmt.Println(c.Keys())
    22. }
    1. 10
    2. [2 4 5 7 8 9 0 1 3 6]
    3. 1
    4. 2
    5. [1 9]

    测试结果

    1. john@john-B85M:~/Workspace/Go/GOPATH/src/gitee.com/johng/gf/g/os/gcache$ go test *.go -bench=".*" -benchmem
    2. goos: linux
    3. goarch: amd64
    4. Benchmark_CacheSet-4 2000000 897 ns/op 249 B/op 4 allocs/op
    5. Benchmark_CacheGet-4 5000000 202 ns/op 49 B/op 1 allocs/op
    6. Benchmark_CacheRemove-4 50000000 35.7 ns/op 0 B/op 0 allocs/op
    7. Benchmark_CacheLruSet-4 1000000 1024 ns/op 399 B/op 4 allocs/op
    8. Benchmark_CacheLruGet-4 3000000 212 ns/op 33 B/op 1 allocs/op
    9. Benchmark_CacheLruRemove-4 50000000 35.9 ns/op 0 B/op 0 allocs/op
    10. Benchmark_InterfaceMapWithLockSet-4 3000000 477 ns/op 73 B/op 2 allocs/op
    11. Benchmark_InterfaceMapWithLockGet-4 10000000 149 ns/op 0 B/op 0 allocs/op
    12. Benchmark_InterfaceMapWithLockRemove-4 50000000 39.8 ns/op 0 B/op 0 allocs/op
    13. Benchmark_IntMapWithLockWithLockSet-4 5000000 304 ns/op 53 B/op 0 allocs/op
    14. Benchmark_IntMapWithLockGet-4 20000000 164 ns/op 0 B/op 0 allocs/op
    15. Benchmark_IntMapWithLockRemove-4 50000000 33.1 ns/op 0 B/op 0 allocs/op
    16. PASS
    17. ok command-line-arguments 47.503s