Go 實現可複用的通用內存緩存

本文介紹瞭如何在 Go 語言中創建一個可重用的內存通用緩存,並提供了具體的實現代碼和使用示例。

Prerequisites

實現

首先,創建一個 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