cache

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

你可以在 GitHubcache - 图1在新窗口打开 上阅读该中间件的源码或通过 pkg.go.devcache - 图2在新窗口打开 查看 API 文档。

下载安装

Go 语言的最低版本要求为 1.16

  1. go get github.com/flamego/cache

存储后端

内存

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

  1. package main
  2. import (
  3. "net/http"
  4. "time"
  5. "github.com/flamego/cache"
  6. "github.com/flamego/flamego"
  7. )
  8. func main() {
  9. f := flamego.Classic()
  10. f.Use(cache.Cacher())
  11. f.Get("/set", func(r *http.Request, cache cache.Cache) error {
  12. return cache.Set(r.Context(), "cooldown", true, time.Minute)
  13. })
  14. f.Get("/get", func(r *http.Request, cache cache.Cache) string {
  15. v, err := cache.Get(r.Context(), "cooldown")
  16. if err != nil && err != os.ErrNotExist {
  17. return err.Error()
  18. }
  19. cooldown, ok := v.(bool)
  20. if !ok || !cooldown {
  21. return "It has been cooled"
  22. }
  23. return "Still hot"
  24. })
  25. f.Run()
  26. }

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

文件系统

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

  1. package main
  2. import (
  3. "net/http"
  4. "os"
  5. "path/filepath"
  6. "time"
  7. "github.com/flamego/cache"
  8. "github.com/flamego/flamego"
  9. )
  10. func main() {
  11. f := flamego.Classic()
  12. f.Use(cache.Cacher(
  13. cache.Options{
  14. Initer: cache.FileIniter(),
  15. Config: cache.FileConfig{
  16. RootDir: filepath.Join(os.TempDir(), "cache"),
  17. },
  18. },
  19. ))
  20. f.Get("/set", func(r *http.Request, cache cache.Cache) error {
  21. return cache.Set(r.Context(), "cooldown", true, time.Minute)
  22. })
  23. f.Get("/get", func(r *http.Request, cache cache.Cache) string {
  24. v, err := cache.Get(r.Context(), "cooldown")
  25. if err != nil && err != os.ErrNotExist {
  26. return err.Error()
  27. }
  28. cooldown, ok := v.(bool)
  29. if !ok || !cooldown {
  30. return "It has been cooled"
  31. }
  32. return "Still hot"
  33. })
  34. f.Run()
  35. }

PostgreSQL

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

  1. package main
  2. import (
  3. "net/http"
  4. "os"
  5. "time"
  6. "github.com/flamego/cache"
  7. "github.com/flamego/cache/postgres"
  8. "github.com/flamego/flamego"
  9. )
  10. func main() {
  11. f := flamego.Classic()
  12. dsn := os.ExpandEnv("postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/$PGDATABASE?sslmode=$PGSSLMODE")
  13. f.Use(cache.Cacher(
  14. cache.Options{
  15. Initer: postgres.Initer(),
  16. Config: postgres.Config{
  17. DSN: dsn,
  18. Table: "cache",
  19. InitTable: true,
  20. },
  21. },
  22. ))
  23. f.Get("/set", func(r *http.Request, cache cache.Cache) error {
  24. return cache.Set(r.Context(), "cooldown", true, time.Minute)
  25. })
  26. f.Get("/get", func(r *http.Request, cache cache.Cache) string {
  27. v, err := cache.Get(r.Context(), "cooldown")
  28. if err != nil && err != os.ErrNotExist {
  29. return err.Error()
  30. }
  31. cooldown, ok := v.(bool)
  32. if !ok || !cooldown {
  33. return "It has been cooled"
  34. }
  35. return "Still hot"
  36. })
  37. f.Run()
  38. }

MySQL

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

  1. package main
  2. import (
  3. "net/http"
  4. "os"
  5. "time"
  6. "github.com/flamego/cache"
  7. "github.com/flamego/cache/mysql"
  8. "github.com/flamego/flamego"
  9. )
  10. func main() {
  11. f := flamego.Classic()
  12. dsn := os.ExpandEnv("$MYSQL_USER:$MYSQL_PASSWORD@tcp($MYSQL_HOST:$MYSQL_PORT)/$MYSQL_DATABASE?charset=utf8&parseTime=true")
  13. f.Use(cache.Cacher(
  14. cache.Options{
  15. Initer: mysql.Initer(),
  16. Config: mysql.Config{
  17. DSN: dsn,
  18. Table: "cache",
  19. InitTable: true,
  20. },
  21. },
  22. ))
  23. f.Get("/set", func(r *http.Request, cache cache.Cache) error {
  24. return cache.Set(r.Context(), "cooldown", true, time.Minute)
  25. })
  26. f.Get("/get", func(r *http.Request, cache cache.Cache) string {
  27. v, err := cache.Get(r.Context(), "cooldown")
  28. if err != nil && err != os.ErrNotExist {
  29. return err.Error()
  30. }
  31. cooldown, ok := v.(bool)
  32. if !ok || !cooldown {
  33. return "It has been cooled"
  34. }
  35. return "Still hot"
  36. })
  37. f.Run()
  38. }

Redis

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

  1. package main
  2. import (
  3. "net/http"
  4. "os"
  5. "time"
  6. "github.com/flamego/cache"
  7. "github.com/flamego/cache/redis"
  8. "github.com/flamego/flamego"
  9. )
  10. func main() {
  11. f := flamego.Classic()
  12. f.Use(cache.Cacher(
  13. cache.Options{
  14. Initer: redis.Initer(),
  15. Config: redis.Config{
  16. Options: &redis.Options{
  17. Addr: os.ExpandEnv("$REDIS_HOST:$REDIS_PORT"),
  18. DB: 15,
  19. },
  20. },
  21. },
  22. ))
  23. f.Get("/set", func(r *http.Request, cache cache.Cache) error {
  24. return cache.Set(r.Context(), "cooldown", true, time.Minute)
  25. })
  26. f.Get("/get", func(r *http.Request, cache cache.Cache) string {
  27. v, err := cache.Get(r.Context(), "cooldown")
  28. if err != nil && err != os.ErrNotExist {
  29. return err.Error()
  30. }
  31. cooldown, ok := v.(bool)
  32. if !ok || !cooldown {
  33. return "It has been cooled"
  34. }
  35. return "Still hot"
  36. })
  37. f.Run()
  38. }

MongoDB

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

  1. package main
  2. import (
  3. "net/http"
  4. "os"
  5. "time"
  6. "github.com/flamego/cache"
  7. "github.com/flamego/cache/mongo"
  8. "github.com/flamego/flamego"
  9. "go.mongodb.org/mongo-driver/mongo/options"
  10. )
  11. func main() {
  12. f := flamego.Classic()
  13. f.Use(cache.Cacher(
  14. cache.Options{
  15. Initer: mongo.Initer(),
  16. Config: mongo.Config{
  17. Options: options.Client().ApplyURI(os.Getenv("MONGODB_URI")),
  18. Database: os.Getenv("MONGODB_DATABASE"),
  19. Collection: "cache",
  20. },
  21. },
  22. ))
  23. f.Get("/set", func(r *http.Request, cache cache.Cache) error {
  24. return cache.Set(r.Context(), "cooldown", true, time.Minute)
  25. })
  26. f.Get("/get", func(r *http.Request, cache cache.Cache) string {
  27. v, err := cache.Get(r.Context(), "cooldown")
  28. if err != nil && err != os.ErrNotExist {
  29. return err.Error()
  30. }
  31. cooldown, ok := v.(bool)
  32. if !ok || !cooldown {
  33. return "It has been cooled"
  34. }
  35. return "Still hot"
  36. })
  37. f.Run()
  38. }

存储类型支持

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

  1. gob.Register(time.Duration(0))

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