Go でコンテキストを使用してリクエスト結果キャッシュの自動更新を実装する方法
要約:
Web アプリケーション開発では、ユーザー エクスペリエンスを向上させるために、一部のリクエストの結果をキャッシュする必要がある場合があります。データベースや他のサービスへのアクセスを減らすため。しかし、キャッシュされたデータの有効期限が問題となり、キャッシュが期限切れになると期限切れのデータを取得してしまい、表示や動作が誤ってしまう可能性があります。この記事では、Go のコンテキスト パッケージを使用してリクエスト結果キャッシュの自動更新機能を実装し、キャッシュされたデータの適時性を確保する方法を検討します。
type CacheItem struct { result interface{} expireAt time.Time } type Cache struct { cacheMap map[string]CacheItem mutex sync.RWMutex }
上記のコードでは、マップを使用してキャッシュ アイテムを保存します。キーはリクエストに関連する一意の識別子、値はキャッシュ アイテムの詳細 (結果や有効期限など)。同時実行の安全性を確保するために、ミューテックス ロックを使用します。
次に、キャッシュ データを取得する関数を作成する必要があります。この関数は、まずリクエスト結果がキャッシュに存在するかどうかを確認し、期限切れかどうかを判断します。キャッシュされた結果が存在し、有効期限が切れていない場合は、キャッシュされたデータが直接返されます。それ以外の場合は、実際のリクエストを行って結果をキャッシュする必要があります。コードは次のとおりです。
func (c *Cache) Get(key string) interface{} { c.mutex.RLock() defer c.mutex.RUnlock() item, ok := c.cacheMap[key] if ok && item.expireAt.After(time.Now()) { return item.result } // 发起请求并更新缓存 result := makeRequest(key) c.cacheMap[key] = CacheItem{result: result, expireAt: time.Now().Add(time.Minute)} return result }
上記のコードでは、同時実行の安全性を確保するために読み取りロックを使用してキャッシュ項目を読み取ります。キャッシュ項目が存在し、有効期限が切れていない場合は、キャッシュ結果が直接返されます。そうでない場合は、実際のリクエストが開始され、リクエスト結果がキャッシュに保存されます。
func (c *Cache) RefreshCache(ctx context.Context, key string) { ticker := time.NewTicker(time.Minute) defer ticker.Stop() for { select { case <-ticker.C: result := makeRequest(key) c.mutex.Lock() c.cacheMap[key] = CacheItem{result: result, expireAt: time.Now().Add(time.Minute)} c.mutex.Unlock() case <-ctx.Done(): return } } }
上記のコードでは、Ticker オブジェクトを使用して makeRequest 関数を定期的に呼び出し、キャッシュを更新します。同時に、select ステートメントを使用してリッスンします。コンテキストがキャンセルされた後にリフレッシュ ループを終了するためのコンテキスト キャンセル信号。
package main import ( "context" "fmt" "net/http" "sync" "time" ) type CacheItem struct { result interface{} expireAt time.Time } type Cache struct { cacheMap map[string]CacheItem mutex sync.RWMutex } func makeRequest(key string) interface{} { // 模拟请求耗时 time.Sleep(time.Second) return fmt.Sprintf("result for %s", key) } func (c *Cache) Get(key string) interface{} { c.mutex.RLock() defer c.mutex.RUnlock() item, ok := c.cacheMap[key] if ok && item.expireAt.After(time.Now()) { return item.result } result := makeRequest(key) c.cacheMap[key] = CacheItem{result: result, expireAt: time.Now().Add(time.Minute)} return result } func (c *Cache) RefreshCache(ctx context.Context, key string) { ticker := time.NewTicker(time.Minute) defer ticker.Stop() for { select { case <-ticker.C: result := makeRequest(key) c.mutex.Lock() c.cacheMap[key] = CacheItem{result: result, expireAt: time.Now().Add(time.Minute)} c.mutex.Unlock() case <-ctx.Done(): return } } } func main() { cache := &Cache{cacheMap: make(map[string]CacheItem)} http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second*5)) defer cancel() key := r.URL.Path result := cache.Get(key) fmt.Fprintf(w, "%s: %s", key, result) // 启动刷新缓存的协程 go cache.RefreshCache(ctx, key) }) http.ListenAndServe(":8080", nil) }
上記のコード例では、単純な HTTP サーバーを定義しています。リクエストを受信すると、キャッシュされた Get メソッドが呼び出されてデータを取得し、クライアントに返されます。 。同時に、コンテキスト パッケージを使用して 5 秒の期限を持つコンテキストを作成し、それを RefreshCache メソッドに渡してキャッシュの更新時間を制御します。
結論:
この記事では、Go の context パッケージを使用して、リクエスト結果キャッシュの自動更新機能を実装する方法を紹介します。キャッシュ構造とミューテックスを使用して同時実行の安全性を確保し、コンテキスト パッケージの機能を使用してキャッシュを定期的に更新することで、リクエスト結果を簡単にキャッシュしてデータの適時性を確保できます。上記のコード例は単なるデモであり、実際に使用するには、特定のニーズに基づいて適切な変更と最適化が必要になる場合があります。
以上がGo でコンテキストを使用してリクエスト結果キャッシュの自動リフレッシュを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。