使用gin封装一个web脚手架(十二):缓存模块

395 阅读1分钟

先创建一个cache文件夹和cache.go

设计好缓存模块的接口

package cache

import "time"

type CacheContract interface {
   Put(key string, value string, ttl time.Duration) error
   Get(key string) (string, error)
}

基于redis实现缓存

package redisCache

import (
   "context"
   "myGin/redis"
   "time"
)

type redisCache struct {
}

func NewRedisCache() *redisCache {

   return &redisCache{}
}

func (r redisCache) Put(key string, value string, ttl time.Duration) error {
   //TODO implement me

   _, err := redis.Client().Set(context.TODO(), key, value, ttl).Result()

   return err
}

func (r redisCache) Get(key string) (string, error) {
   //TODO implement me

   return redis.Client().Get(context.TODO(), key).Result()

}

基于file实现缓存

先创建storage文件夹

package fileCache

import (
   "crypto/md5"
   "encoding/json"
   "errors"
   "fmt"
   "io/ioutil"
   "os"
   "time"
)

type fileCache struct {
}

type structure struct {
   Data   string `json:"data"`
   Expire int    `json:"expire"`
}

func NewFileCache() *fileCache {

   return &fileCache{}
}

func (f fileCache) Put(key string, value string, ttl time.Duration) error {
   //TODO implement me

   //key的md5作为文件名
   file, err := os.OpenFile("storage/"+fmt.Sprintf("%x", md5.Sum([]byte(key))), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0644)

   if err != nil {

      return err
   }

   defer file.Close()

   var v structure

   v.Data = value

   //设置过期时间
   if ttl == 0 {

      v.Expire = 0
   } else {

      v.Expire = int(time.Now().Add(ttl).Unix())
   }

   jsonStr, err := json.Marshal(v)

   if err != nil {

      return err
   }

   _, err = file.Write(jsonStr)

   return err

}

func (f fileCache) Get(key string) (string, error) {
   //TODO implement me

   filePath := "storage/" + fmt.Sprintf("%x", md5.Sum([]byte(key)))

   file, err := os.Open(filePath)

   if err != nil {

      return "", err
   }

   defer file.Close()

   data, err := ioutil.ReadAll(file)

   if err != nil {

      return "", err
   }

   var v structure

   err = json.Unmarshal(data, &v)

   if err != nil {

      return "", err
   }

   now := time.Now().Unix()

   //判断过期时间
   if v.Expire != 0 && (now > int64(v.Expire)) {

      //删除过期文件
      defer func(f *os.File, ff string) {

         f.Close()

         os.Remove(ff)

      }(file, filePath)

      return "", errors.New("缓存已超时")
   }

   return v.Data, err

}

使用工厂模式来切换驱动

package cache

import (
   "myGin/cache/fileCache"
   "myGin/cache/redisCache"
   "time"
)

type CacheContract interface {
   Put(key string, value string, ttl time.Duration) error
   Get(key string) (string, error)
}

func Cache(driver string) CacheContract {

   switch driver {

   case "redis":

      return redisCache.NewRedisCache()

   case "file":

      return fileCache.NewFileCache()

   }

   return redisCache.NewRedisCache()
}

调用

package main

import (
   "myGin/cache"
   "time"
)

func main() {

   c := cache.Cache("file")

   c.Put("peter", "nice", 1*time.Minute)

   c.Get("peter")

}

源代码:github.com/PeterYangs/…