Go 實現可複用的通用內存緩存
本文介紹瞭如何在 Go 語言中創建一個可重用的內存通用緩存,並提供了具體的實現代碼和使用示例。
Prerequisites
-
安裝 Go
-
go-cache package[1]
實現
首先,創建一個 cache package,它包含我們正在構建的緩存的代碼。
package cache
import (
"time"
"github.com/patrickmn/go-cache"
)
使用泛型實現一個 cache struct:
type Cache[K any, T any] struct {
cache *cache.Cache
}
添加構造函數:
package cache
import (
"time"
"github.com/patrickmn/go-cache"
)
type Cache[K any, T any] struct {
cache *cache.Cache
}
func New[K any, T any](defaultExpiration time.Duration, cleanupInterval time.Duration) *Cache[K, T] {
c := cache.New(defaultExpiration, cleanupInterval)
return &Cache[K, T]{
cache: c,
}
}
我們使用 go-cache 包創建緩存,並傳遞一些過期時間。
現在,我們可以添加用於設置值和獲取值的方法:
package cache
import (
"time"
"github.com/patrickmn/go-cache"
)
type Cache[K any, T any] struct {
cache *cache.Cache
}
func New[K any, T any](defaultExpiration time.Duration, cleanupInterval time.Duration) *Cache[K, T] {
c := cache.New(defaultExpiration, cleanupInterval)
return &Cache[K, T]{
cache: c,
}
}
func (c *Cache[K, T]) Set(key K, val any) {
c.cache.Set(string(key), val, cache.DefaultExpiration)
}
func (c *Cache[K, T]) Get(key K) (*T, bool) {
v, ok := c.cache.Get(string(key))
if !ok {
return nil, false
}
vTyped, ok := v.(T)
if !ok {
return nil, false
}
return &vTyped, true
}
Set 方法很簡單:我們傳遞鍵和要緩存的值,但等等!有一個問題:go-cache 使用字符串作爲緩存項的鍵,而我們的通用類型是任意類型,所以編譯器不允許我們在這裏使用它。我們需要創建一個自定義約束。
自定義約束是一個接口,我們可以在這裏描述可以使用哪些類型的結構作爲泛型參數。
我們將創建這個約束:
type stringConstraint interface {
~string
}
對於類型約束,我們通常並不關心特定的類型,如字符串;我們感興趣的是所有的字符串類型。這就是 ~ 標記的作用。表達式 ~string 表示底層類型爲 string 的所有類型的集合。這包括字符串類型本身,以及所有用定義聲明的類型,如 MyString string 類型
package cache
import (
"time"
"github.com/patrickmn/go-cache"
)
type stringConstraint interface {
~string
}
type Cache[K stringConstraint, T any] struct {
cache *cache.Cache
}
func New[K stringConstraint, T any](defaultExpiration time.Duration, cleanupInterval time.Duration) *Cache[K, T] {
c := cache.New(defaultExpiration, cleanupInterval)
return &Cache[K, T]{
cache: c,
}
}
func (c *Cache[K, T]) Set(key K, val any) {
c.cache.Set(string(key), val, cache.DefaultExpiration)
}
func (c *Cache[K, T]) Get(key K) (*T, bool) {
v, ok := c.cache.Get(string(key))
if !ok {
return nil, false
}
vTyped, ok := v.(T)
if !ok {
return nil, false
}
return &vTyped, true
}
我們最終的自定義通用緩存代碼如上所示,實現起來還算簡單。
參考資料
[1]
go-cache github: https://github.com/patrickmn/go-cache
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/-3Zt8ZyMZAHFPTKHDvggVQ