emahiro/b.log

日々の勉強の記録とか育児の記録とか。

glc(go local cache) というライブラリを作りました

[]byte でローカルにキャッシュを保存する glc (go local cache) というライブラリを作ってみました。

Motivation

APIのレスポンスやそんなに頻繁に更新しないデータを一定時間ローカルにキャッシュとして持っておきたいケースは多いと思います。

Go であれば https://github.com/patrickmn/go-cache などのオンメモリにキャッシュするライブラリを使うのが一般的かなと思いますが、上記のライブラリは interface を受けて interface を返す仕様のため、Set するときはなんでも突っ込めば key に合わせてキャッシュをセットしてくれますが、取り出すときも interface のために取り出した側で適切にキャストないし、デコードすることが必要でした。

使う側でキャストすることに違和感があったのでそれなら使う側で []byteエンコードしてしまって、[]byte を受け取って []byte を返すだけの小さな仕様のライブラリがあってもいいかなーと思ったのと、どうやら go-cache は公式には Go Module を現時点では考えてないっぽい?という issue も見つけた(※.1)ので、今後のことを考えて自作で「ローカルキャッシュする君」を作ってみました。

この Go Local Cache はあくまで []byte に変換した値に有効期限をつけてメモリ(orファイル上)に保存するものなので、もし変換するコストをかけたくないのであれば go-cache を使う方がいいと思います。

繰り返しですが、go-cache だと使う側でキャストすることが必要になりますが、それが少し気持ち悪かったのがこれを作ったモチベーションです。
go-cache で要件を満たせるのであればそちらを使うでもいいかと思います。

※1. https://github.com/patrickmn/go-cache/pull/89
この issune に記載されてることは若干疑問ではある。
(普通に go.mod 対応して新しくバージョン切って go get github.com/patrickmn/go-cache@v2.X.X で行けそうな気もする。)

How to Use

In memory cache

README の通りです。

[]byte 型に変換してしてしまえばどんな値でも保存できます。

Local file cache

Go Local Cache を唄っているので local でのファイルキャッシュも実装しました。

使い方は In memory cache と似ています。内部実装としては NewFileCache を実行するタイミングで prefix に指定したディレクトリを新しく作成してそこに key で指定したファイル名でファイルを作成していきます。

FileCache オブジェクトはファイルキャッシュを使用するパッケージごとに作成するとパッケージごとに同一のファイルキャッシュ用のディレクトリを参照するようになります。

なお、このファイルキャッシュの昨日は Google App Engine でも使えます(※1)

※1. tempファイルにキャッシュ用のディレクトリを作成するため。
ref: 一時ファイルの読み取りと書き込み

感想

ちょうど業務で似たような機能を作る機会があったので、単純な機能だけ切り出してライブラリにしてみました。
ヘビーに使うかはわからないですが、少なくとも自分がほしいと思うものは作れたんじゃないかなと思います。

作ってる最中にもメソッドのシグネチャ悩んだり、MemoryCacheの構造を悩んだり、さっと実装してみたら思ってた振る舞いをしないものを作っていたりと、コードはとても小さいですが、汎用的に作るものの難しさをやはり痛感しました。

ちなみにすでに業務で一部投入してるので商用環境で動いてる実績あります(最後にささやかなアピール笑)