DEV Community

y-yagi
y-yagi

Posted on

Intro to `cacher` that simple cache library

#go

I created the cache library for the Go language. It's named cacher.
GitHub: https://github.com/y-yagi/cacher

cacher supports to use a file system to store cache data.

Why this need?

I create CLI tools often and sometimes want to use cache in that. For example, when the same HTTP API is called many times and the result of API rarely changes.
Normally, using Redis or memcached(or something similar) for the cache. But in the case of CLI, it may not be using those middlewares. So I wanted a cache library that supports to file system.

How to use

Example:

package main

import (
    "fmt"
    "time"

    "github.com/y-yagi/cacher"
)

func main() {
    // Specify a directory that stores cache data.
    c := cacher.WithFileStore("/tmp/")

    // Arguments are cache key, data and expiry time. If uses `cacher.Forever`, cache never expires.
    c.Write("cache-key", []byte("value"), cacher.Forever)
    value, _ := c.Read("cache-key")
    fmt.Print(string(value))

    c.Write("cache-key2", []byte("value"), 1*time.Second)

    time.Sleep(2 * time.Second)

    // If the cache expired. `Read` returns nil.
    value, _ = c.Read("cache-key2")
    fmt.Print(string(value))
}

For more detail, please see the API doc.

How to store data to file?

Go supports multiple formats to store data. This time I use gob package. The gob package can handle Go data structure as is. A simple example is followed.

package main

import (
    "bytes"
    "encoding/gob"
    "fmt"
    "log"
)

type entry struct {
    Value      []byte
    Expiration int64
}

func main() {
    e := &entry{Value: []byte("value"), Expiration: 0}
    encodedEntry := encode(e)

    fmt.Printf("%#v\n", encodedEntry)

    decodedEntry := decode(encodedEntry)
    fmt.Printf("%#v\n", decodedEntry)
}

func encode(e *entry) []byte {
    buf := bytes.NewBuffer(nil)
    err := gob.NewEncoder(buf).Encode(e)
    if err != nil {
        log.Fatal("encode error:", err)
    }
    return buf.Bytes()
}

func decode(data []byte) *entry {
    var e entry
    buf := bytes.NewBuffer(data)
    err := gob.NewDecoder(buf).Decode(&e)
    if err != nil {
        log.Fatal("decode error:", err)
    }
    return &e
}

For more detail, please see the blog entry and API doc.

Wrapping up

I introduced my cache library that assumed to using CLI. But may more appropriate approaches/libraries exist I think. If you know something, please tell me. Thanks!

Top comments (0)