基本介绍
gcache
是提供统一的缓存管理模块,提供了开发者可自定义灵活接入的缓存适配接口,并默认提供了高速内存缓存适配实现。
使用方式:
import "github.com/gogf/gf/v2/os/gcache"
接口文档:
https://pkg.go.dev/github.com/gogf/gf/v2/os/gcache
简要介绍:
-
gcache
默认提供默认的高速内存缓存对象,可以通过包方法操作内存缓存,也可以通过New
方法创建内存缓存对象。在通过包方法使用缓存功能时,操作的是gcache
默认提供的一个gcache.Cache
对象,具有全局性,因此在使用时注意全局键名的覆盖。 -
gcache
使用的键名类型是interface{}
,而不是string
类型,这意味着我们可以使用任意类型的变量作为键名,但大多数时候建议使用string
或者[]byte
作为键名,并且统一键名的数据类型,以便维护。 -
gcache
存储的键值类型是interface{}
,也就是说可以存储任意的数据类型,当获取数据时返回的也是interface{}
类型,若需要转换为其他的类型可以通过gcache
的Get*
方法便捷获取常见类型。注意,如果您确定知道自己使用的是内存缓存,那么可以直接使用断言方式 对返回的interface{}
变量进行类型转换,否则建议通过获取到的泛型对象对应方法完成类型转换。 -
另外需要注意的是,
gcache
的缓存过期时间参数duration
的类型为time.Duration
类型,在Set
缓存变量时,如果缓存时间参数duration = 0
表示不过期,duration < 0
表示立即过期,duration > 0
表示超时过期。
注意事项
关于键名数据类型
大家可以发现缓存组件中关于键值对的数据类型都是 interface{}
,这种设计主要是为了考虑通用性和易用性,但是使用上需要注意 interface{}
的比较:只有 数据 和 类型 都相等才算真正匹配。我们来看个例子。
package main
import (
"fmt"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gctx"
)
func main() {
var (
ctx = gctx.New()
key1 int32 = 1
key2 float64 = 1
value = `value`
)
_ = gcache.Set(ctx, key1, value, 0)
fmt.Println(gcache.MustGet(ctx, key1).Val())
fmt.Println(gcache.MustGet(ctx, key2).Val())
}
执行后,终端输出:
<nil>
可以看到,虽然 key1
和 key2
的数值都是相同的,但是两者类型不同,因此通过 key2
无法获取到键值。
关于获取对象键值
由于键值的类型也是 interface{}
,往往在获取后会通过类型转换为需要的数据类型。常见的类型转换是直接使用类型断言,这种做法有种风险,就是由于 gcache
组件采用 适配器接口设计模式,因此底层的实现上(除了默认的内存适配器)往往会改变原有的数据类型(非内存实现往往都会涉及到序列化/反序列化存储),因此不推荐大家直接使用类型断言进行数据类型转换。
因此缓存组件在获取键值上做了改进,并不是直接返回 interface{}
的键值类型,而是以框架泛型 *gvar.Var
对象返回,开发者根据业务场景转换为所需的数据类型。特别是针对于对象缓存存储和读取的场景特别有用,我们来看一个示例:
package main
import (
"fmt"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gctx"
)
func main() {
type User struct {
Id int
Name string
Site string
}
var (
ctx = gctx.New()
user *User
key = `UserKey`
value = &User{
Id: 1,
Name: "GoFrame",
Site: "https://goframe.org",
}
)
err := gcache.Set(ctx, key, value, 0)
if err != nil {
panic(err)
}
v, err := gcache.Get(ctx, key)
if err != nil {
panic(err)
}
if err = v.Scan(&user); err != nil {
panic(err)
}
fmt.Printf(`%#v`, user)
}
执行后,终端输出:
&main.User{Id:1, Name:"GoFrame", Site:"https://goframe.org"}