cache

cache 中间件为 Flame 实例提供缓存数据管理服务,支持的存储后端包括内存、文件系统、PostgreSQL、MySQL、Redis、MongoDB 和 SQLite。

你可以在 GitHub在新窗口打开 上阅读该中间件的源码或通过 pkg.go.dev在新窗口打开 查看 API 文档。

下载安装

go get github.com/flamego/cache

存储后端

内存

cache.Cacher在新窗口打开 可以配合 cache.Options在新窗口打开 对中间件进行配置,并默认使用内存作为存储后端:

package main

import (
	"net/http"
	"time"

	"github.com/flamego/cache"
	"github.com/flamego/flamego"
)

func main() {
	f := flamego.Classic()
	f.Use(cache.Cacher())
	f.Get("/set", func(r *http.Request, cache cache.Cache) error {
		return cache.Set(r.Context(), "cooldown", true, time.Minute)
	})
	f.Get("/get", func(r *http.Request, cache cache.Cache) string {
		v, err := cache.Get(r.Context(), "cooldown")
		if err != nil && err != os.ErrNotExist {
			return err.Error()
		}

		cooldown, ok := v.(bool)
		if !ok || !cooldown {
			return "It has been cooled"
		}
		return "Still hot"
	})
	f.Run()
}

由于数据存储在内存中,因此会在应用退出后被清除。如需持久化缓存数据,请选择其它存储后端。

文件系统

cache.FileIniter在新窗口打开 是文件系统存储后端的初始化函数,并可以配合 cache.FileConfig在新窗口打开 对其进行配置:

package main

import (
	"net/http"
	"os"
	"path/filepath"
	"time"

	"github.com/flamego/cache"
	"github.com/flamego/flamego"
)

func main() {
	f := flamego.Classic()
	f.Use(cache.Cacher(
		cache.Options{
			Initer: cache.FileIniter(),
			Config: cache.FileConfig{
				RootDir: filepath.Join(os.TempDir(), "cache"),
			},
		},
	))
	f.Get("/set", func(r *http.Request, cache cache.Cache) error {
		return cache.Set(r.Context(), "cooldown", true, time.Minute)
	})
	f.Get("/get", func(r *http.Request, cache cache.Cache) string {
		v, err := cache.Get(r.Context(), "cooldown")
		if err != nil && err != os.ErrNotExist {
			return err.Error()
		}

		cooldown, ok := v.(bool)
		if !ok || !cooldown {
			return "It has been cooled"
		}
		return "Still hot"
	})
	f.Run()
}















 
 
 
 
 
 


















PostgreSQL

postgres.Initer在新窗口打开 是 PostgreSQL 存储后端的初始化函数,并可以配合 postgres.Config在新窗口打开 对其进行配置:

package main

import (
	"net/http"
	"os"
	"time"

	"github.com/flamego/cache"
	"github.com/flamego/cache/postgres"
	"github.com/flamego/flamego"
)

func main() {
	f := flamego.Classic()

	dsn := os.ExpandEnv("postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/$PGDATABASE?sslmode=$PGSSLMODE")
	f.Use(cache.Cacher(
		cache.Options{
			Initer: postgres.Initer(),
			Config: postgres.Config{
				DSN:       dsn,
				Table:     "cache",
				InitTable: true,
			},
		},
	))
	f.Get("/set", func(r *http.Request, cache cache.Cache) error {
		return cache.Set(r.Context(), "cooldown", true, time.Minute)
	})
	f.Get("/get", func(r *http.Request, cache cache.Cache) string {
		v, err := cache.Get(r.Context(), "cooldown")
		if err != nil && err != os.ErrNotExist {
			return err.Error()
		}

		cooldown, ok := v.(bool)
		if !ok || !cooldown {
			return "It has been cooled"
		}
		return "Still hot"
	})
	f.Run()
}

















 
 
 
 
 
 
 
 


















MySQL

mysql.Initer在新窗口打开 是 MySQL 存储后端的初始化函数,并可以配合 mysql.Config在新窗口打开 对其进行配置:

package main

import (
	"net/http"
	"os"
	"time"

	"github.com/flamego/cache"
	"github.com/flamego/cache/mysql"
	"github.com/flamego/flamego"
)

func main() {
	f := flamego.Classic()

	dsn := os.ExpandEnv("$MYSQL_USER:$MYSQL_PASSWORD@tcp($MYSQL_HOST:$MYSQL_PORT)/$MYSQL_DATABASE?charset=utf8&parseTime=true")
	f.Use(cache.Cacher(
		cache.Options{
			Initer: mysql.Initer(),
			Config: mysql.Config{
				DSN:       dsn,
				Table:     "cache",
				InitTable: true,
			},
		},
	))
	f.Get("/set", func(r *http.Request, cache cache.Cache) error {
		return cache.Set(r.Context(), "cooldown", true, time.Minute)
	})
	f.Get("/get", func(r *http.Request, cache cache.Cache) string {
		v, err := cache.Get(r.Context(), "cooldown")
		if err != nil && err != os.ErrNotExist {
			return err.Error()
		}

		cooldown, ok := v.(bool)
		if !ok || !cooldown {
			return "It has been cooled"
		}
		return "Still hot"
	})
	f.Run()
}

















 
 
 
 
 
 
 
 


















Redis

redis.Initer在新窗口打开 是 Redis 存储后端的初始化函数,并可以配合 redis.Config在新窗口打开 对其进行配置:

package main

import (
	"net/http"
	"os"
	"time"

	"github.com/flamego/cache"
	"github.com/flamego/cache/redis"
	"github.com/flamego/flamego"
)

func main() {
	f := flamego.Classic()

	f.Use(cache.Cacher(
		cache.Options{
			Initer: redis.Initer(),
			Config: redis.Config{
				Options: &redis.Options{
					Addr: os.ExpandEnv("$REDIS_HOST:$REDIS_PORT"),
					DB:   15,
				},
			},
		},
	))
	f.Get("/set", func(r *http.Request, cache cache.Cache) error {
		return cache.Set(r.Context(), "cooldown", true, time.Minute)
	})
	f.Get("/get", func(r *http.Request, cache cache.Cache) string {
		v, err := cache.Get(r.Context(), "cooldown")
		if err != nil && err != os.ErrNotExist {
			return err.Error()
		}

		cooldown, ok := v.(bool)
		if !ok || !cooldown {
			return "It has been cooled"
		}
		return "Still hot"
	})
	f.Run()
}
















 
 
 
 
 
 
 
 
 


















MongoDB

mongo.Initer在新窗口打开 是 MongoDB 存储后端的初始化函数,并可以配合 mongo.Config在新窗口打开 对其进行配置:

package main

import (
	"net/http"
	"os"
	"time"

	"github.com/flamego/cache"
	"github.com/flamego/cache/mongo"
	"github.com/flamego/flamego"
	"go.mongodb.org/mongo-driver/mongo/options"
)

func main() {
	f := flamego.Classic()

	f.Use(cache.Cacher(
		cache.Options{
			Initer: mongo.Initer(),
			Config: mongo.Config{
				Options:    options.Client().ApplyURI(os.Getenv("MONGODB_URI")),
				Database:   os.Getenv("MONGODB_DATABASE"),
				Collection: "cache",
			},
		},
	))
	f.Get("/set", func(r *http.Request, cache cache.Cache) error {
		return cache.Set(r.Context(), "cooldown", true, time.Minute)
	})
	f.Get("/get", func(r *http.Request, cache cache.Cache) string {
		v, err := cache.Get(r.Context(), "cooldown")
		if err != nil && err != os.ErrNotExist {
			return err.Error()
		}

		cooldown, ok := v.(bool)
		if !ok || !cooldown {
			return "It has been cooled"
		}
		return "Still hot"
	})
	f.Run()
}

















 
 
 
 
 
 
 
 


















SQLite

sqlite.Initer在新窗口打开 是 SQLite 存储后端的初始化函数,并可以配合 sqlite.Config在新窗口打开 对其进行配置:

package main

import (
	"net/http"
	"os"
	"time"

	"github.com/flamego/cache"
	"github.com/flamego/cache/sqlite"
	"github.com/flamego/flamego"
)

func main() {
	f := flamego.Classic()

	f.Use(cache.Cacher(
		cache.Options{
			Initer: sqlite.Initer(),
			Config: sqlite.Config{
				DSN:       "app.db",
				Table:     "cache",
				InitTable: true,
			},
		},
	))
	f.Get("/set", func(r *http.Request, cache cache.Cache) error {
		return cache.Set(r.Context(), "cooldown", true, time.Minute)
	})
	f.Get("/get", func(r *http.Request, cache cache.Cache) string {
		v, err := cache.Get(r.Context(), "cooldown")
		if err != nil && err != os.ErrNotExist {
			return err.Error()
		}

		cooldown, ok := v.(bool)
		if !ok || !cooldown {
			return "It has been cooled"
		}
		return "Still hot"
	})
	f.Run()
}
















 
 
 
 
 
 
 
 


















存储类型支持

缓存数据的默认编解码格式为 gob在新窗口打开,因此仅支持有限的值类型。如果遇到类似 encode: gob: type not registered for interface: time.Duration 这样的错误,则可以通过 gob.Register在新窗口打开 在应用中将该类型注册到编解码器中解决:

gob.Register(time.Duration(0))

单个应用中对同一类型仅需注册一次。