0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Go】bigcacheの操作をラップしたインターフェースを作ってみた

Last updated at Posted at 2025-04-19

概要

  • Goのin-memory cache packageのbigcacheパッケージを使用したサンプルコードと使用例
    • Get, Setなどの操作をインターフェース化
  • encode / decodeはgobパッケージを使用

サンプルコード

package main

import (
	"bytes"
	"encoding/gob"
	"errors"
	"fmt"

	"github.com/allegro/bigcache/v3"
)

// Cache bigcacheの操作を抽象化したインターフェース
type Cache interface {
	Get(key string, mapper interface{}) error
	Set(key string, value interface{}) error
	Delete(key string) error
	Reset() error
}

type BigCache struct {
	Cache *bigcache.BigCache
}

// NewCache bigcacheのインスタンスを生成する関数
func NewCache(c *bigcache.BigCache) (Cache, error) {
	if c == nil {
		return nil, errors.New("cache instance is nil")
	}
	return &BigCache{
		Cache: c,
	}, nil
}

// 登録済みの型を保持するマップ
var registeredTypes = make(map[string]bool)

// registerType 型を一度だけ登録するための関数
func registerType(value interface{}) {
	if value == nil {
		return
	}
	typeName := fmt.Sprintf("%T", value)
	if !registeredTypes[typeName] {
		gob.Register(value)
		registeredTypes[typeName] = true
	}
}

// Get キャッシュからデータを取得する関数
func (c BigCache) Get(key string, mapper interface{}) error {
	if key == "" {
		return errors.New("key cannot be empty")
	}
	if mapper == nil {
		return errors.New("mapper cannot be nil")
	}

	registerType(mapper)

	entry, err := c.Cache.Get(key)
	if err != nil {
		return err
	}
	return gob.NewDecoder(bytes.NewReader(entry)).Decode(mapper)
}

func (c BigCache) Set(key string, value interface{}) error {
	if key == "" {
		return errors.New("key cannot be empty")
	}
	vb, err := serialize(value)
	if err != nil {
		return err
	}
	return c.Cache.Set(key, vb)
}

// serialize キャッシュに保存するデータをシリアライズする関数
func serialize(value interface{}) ([]byte, error) {
	registerType(value)

	buf := bytes.Buffer{}
	enc := gob.NewEncoder(&buf)

	err := enc.Encode(value)
	if err != nil {
		return nil, fmt.Errorf("failed to encode: %w", err)
	}

	return buf.Bytes(), nil
}

// Delete キャッシュからデータを削除する関数
func (c BigCache) Delete(key string) error {
	if key == "" {
		return errors.New("key cannot be empty")
	}
	return c.Cache.Delete(key)
}

// Reset キャッシュをリセットする関数
func (c BigCache) Reset() error {
	return c.Cache.Reset()
}

使用例

package main

import (
	"context"
	"errors"
	"log"
	"math/big"
	"time"

	"github.com/allegro/bigcache/v3"
)

func main() {
	// bigcacheの設定
	cfg := bigcache.DefaultConfig(10 * time.Minute)
	bigCa, err := bigcache.New(context.Background(), cfg)
	if err != nil {
		log.Fatal(err)
	}

	// bigcacheの操作を抽象化したインスタンスを生成
	cache, err := NewCache(bigCa)
	if err != nil {
		log.Fatal(err)
	}

	// bigint型のデータをキャッシュに保存
	var bigIntValue big.Int
	bigIntValue.SetString("1234567890", 10)

	cache.Set("test-key", &bigIntValue)
	if err != nil {
		log.Fatal(err)
	}

	// キャッシュからデータを取得
	var result big.Int
	err = cache.Get("test-key", &result)
	if err != nil {
		log.Fatal(err)
	}
	println("result:", result.String())

	// キャッシュからデータを削除
	err = cache.Delete("test-key")
	if err != nil {
		log.Fatal(err)
	}

	// Getでキャッシュが空かどうかを確認
	var result2 big.Int
	err = cache.Get("test-key", &result2)
	if err != nil {
		if errors.Is(err, bigcache.ErrEntryNotFound) {
			println(err.Error())
		} else {
			println(err.Error())
		}
	}
	println("result2:", result2.String())
}
// 出力
// result: 1234567890
// Entry not found
// result2: 0
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?