go-cache

キャッシュライブラリGoGolangインメモリキャッシュthread-safe有効期限

GitHub概要

patrickmn/go-cache

An in-memory key:value store/cache (similar to Memcached) library for Go, suitable for single-machine applications.

スター8,675
ウォッチ117
フォーク900
作成日:2012年1月2日
言語:Go
ライセンス:MIT License

トピックス

cachegolibrary

スター履歴

patrickmn/go-cache Star History
データ取得日時: 2025/10/22 08:07

キャッシュライブラリ

go-cache

概要

go-cache(patrickmn/go-cache)は、memcachedに似たGo用のインメモリkey:valueストア/キャッシュライブラリです。単一マシンで動作するアプリケーションに適しており、本質的にthread-safe map[string]interface{}に有効期限を追加した実装です。

詳細

go-cacheは、ネットワーク越しにコンテンツをシリアライズ/送信する必要がないため、非常にシンプルで高速です。任意のオブジェクトを指定した期間または永続的に保存でき、複数のgoroutineから安全に使用できます。キャッシュ全体をファイルに保存したり、ファイルから読み込んだりすることで、ダウンタイムから迅速に復旧できます。

内部的にはデフォルトの有効期限時間(例:5分)とクリーンアップ間隔(例:10分)を設定でき、期限切れアイテムを定期的に削除します。シンプルながら実用的な機能を提供し、Go開発者にとって非常に使いやすいキャッシュソリューションです。

メリット・デメリット

メリット

  • シンプルで直感的なAPI設計
  • thread-safeで複数goroutineから安全にアクセス可能
  • memcachedライクな使い心地
  • ネットワークシリアライゼーション不要で高速
  • 任意のGoオブジェクトを保存可能
  • 自動的な期限切れアイテム削除
  • ファイル保存/読み込み機能によるダウンタイム対応
  • 単一マシンアプリケーションに最適

デメリット

  • 単一マシン限定(分散キャッシュ非対応)
  • 他のキャッシュシステム(Redis、Memcached等)と比べて機能が限定的
  • 大規模データや複雑なキャッシュ戦略には不向き
  • メモリ使用量の詳細制御機能が少ない
  • ネットワーク経由でのアクセスは不可

参考ページ

書き方の例

基本的なセットアップ

package main

import (
    "fmt"
    "time"
    "github.com/patrickmn/go-cache"
)

func main() {
    // デフォルト有効期限5分、クリーンアップ間隔10分でキャッシュを作成
    c := cache.New(5*time.Minute, 10*time.Minute)
}

基本的なSet/Get操作

// 文字列の保存
c.Set("username", "john_doe", cache.DefaultExpiration)

// 任意のオブジェクトの保存
user := map[string]interface{}{
    "id":   123,
    "name": "John Doe",
    "email": "[email protected]",
}
c.Set("user:123", user, cache.DefaultExpiration)

// 値の取得
username, found := c.Get("username")
if found {
    fmt.Printf("Username: %s\n", username.(string))
}

// 型アサーション付きの取得
if userData, found := c.Get("user:123"); found {
    if userMap, ok := userData.(map[string]interface{}); ok {
        fmt.Printf("User: %v\n", userMap)
    }
}

有効期限の指定

// 1時間後に有効期限切れ
c.Set("temp_data", "temporary", 1*time.Hour)

// 永続的に保存(有効期限なし)
c.Set("config", "permanent_value", cache.NoExpiration)

// デフォルト有効期限を使用
c.Set("default_ttl", "uses_default", cache.DefaultExpiration)

// 10秒後に有効期限切れ
c.Set("short_lived", "quick_access", 10*time.Second)

追加とインクリメント操作

// AddはキーがまだAbsorption場合のみ追加
err := c.Add("counter", 1, cache.DefaultExpiration)
if err != nil {
    fmt.Printf("Key already exists: %v\n", err)
}

// 数値のインクリメント
c.Set("views", 100, cache.DefaultExpiration)
newValue, err := c.Increment("views", 1)
if err == nil {
    fmt.Printf("New view count: %d\n", newValue)
}

// デクリメント
newValue, err = c.Decrement("views", 5)
if err == nil {
    fmt.Printf("Decremented view count: %d\n", newValue)
}

// float64でのインクリメント
c.Set("score", 10.5, cache.DefaultExpiration)
newScore, err := c.IncrementFloat("score", 2.3)
if err == nil {
    fmt.Printf("New score: %.2f\n", newScore)
}

キャッシュの管理操作

// アイテムの削除
c.Delete("username")

// キーの存在確認(期限切れチェック込み)
_, found := c.Get("user:123")
fmt.Printf("User exists: %t\n", found)

// 全アイテムの取得
items := c.Items()
fmt.Printf("Total items: %d\n", len(items))

// 期限切れアイテムの手動削除
c.DeleteExpired()

// 全キャッシュのクリア
c.Flush()

有効期限の確認と更新

// アイテムの有効期限確認
if item, found := c.get("user:123"); found {
    fmt.Printf("Expires at: %v\n", item.Expiration)
}

// 有効期限の更新(既存値を維持して期限のみ変更)
if currentValue, found := c.Get("user:123"); found {
    c.Set("user:123", currentValue, 2*time.Hour) // 2時間に延長
}

// TTLの実装(Goの標準ライブラリを使用)
func getTTL(c *cache.Cache, key string) time.Duration {
    if item, found := c.get(key); found {
        if item.Expiration > 0 {
            return time.Until(time.Unix(0, item.Expiration))
        }
        return -1 // NoExpiration
    }
    return 0 // Not found
}

ファイル保存と復元

// キャッシュをファイルに保存
items := c.Items()
err := saveToFile("cache_backup.gob", items)
if err != nil {
    fmt.Printf("Save error: %v\n", err)
}

// ファイルからキャッシュを復元
items, err := loadFromFile("cache_backup.gob")
if err != nil {
    fmt.Printf("Load error: %v\n", err)
} else {
    // 復元されたアイテムで新しいキャッシュを作成
    restoredCache := cache.NewFrom(cache.DefaultExpiration, 10*time.Minute, items)
}

// ファイル保存のヘルパー関数例
func saveToFile(filename string, items map[string]cache.Item) error {
    // encoding/gobやjsonを使用してシリアライズ
    // 実装は具体的な要件に応じて行う
    return nil
}

設定とカスタマイズ

// カスタムクリーンアップ間隔
c := cache.New(30*time.Minute, 1*time.Minute) // 1分毎にクリーンアップ

// クリーンアップの無効化(手動管理)
c := cache.New(30*time.Minute, -1)

// カスタムコールバック機能(疑似実装)
c.OnEvicted(func(key string, value interface{}) {
    fmt.Printf("Evicted: %s = %v\n", key, value)
})

// 使用統計の追跡(独自実装が必要)
type StatsCache struct {
    *cache.Cache
    hits   int64
    misses int64
}

func (s *StatsCache) Get(key string) (interface{}, bool) {
    value, found := s.Cache.Get(key)
    if found {
        s.hits++
    } else {
        s.misses++
    }
    return value, found
}