1 Star 1 Fork 0

Yel/gocache

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
local_cache.go 6.12 KB
一键复制 编辑 原始数据 按行查看 历史
yel 提交于 2023-04-14 17:42 +08:00 . 1、优化使用方式
package drivers
import (
"crypto/md5"
"encoding/gob"
"encoding/hex"
"os"
"path"
"strings"
"time"
"gitee.com/yelhjt/gocache/config"
"gitee.com/yelhjt/gocache/core"
)
// 本地缓存
type localCache struct {
// 缓存
*core.Cache
// 配置
config *config.LocalConfig
}
// 实例化
func NewLocal(conf *config.LocalConfig) core.CacheInterface {
local_cache := &localCache{
Cache: &core.Cache{
// 不过期时间
NoExpire: core.NoExpire,
// 前缀
Prefix: conf.Prefix,
// 缓存数据
Items: make(map[string]core.Item),
},
config: conf,
}
return local_cache
}
//----------------------------------
// 实现 CacheInterface 接口 start
//----------------------------------
/**
* 获取值
*/
func (local_cache *localCache) Get(key string, defaultvalue interface{}) (interface{}, error) {
// 获取文件路径
value, err := local_cache.getRaw(key)
// 如果文件不存在 或者 缓存过期,返回默认值
if err == core.NoCacheFile || err == core.CacheExpire {
return defaultvalue, nil
}
if err != nil {
return nil, err
}
return value, nil
}
/**
* 设置值
*/
func (local_cache *localCache) Set(key string, value interface{}, d time.Duration) bool {
// 设置值
_, errs := local_cache.set(key, value, d)
if errs != nil {
return false
}
return true
}
/**
* 设置值 此名字则存在则报错
*/
func (local_cache *localCache) Add(key string, value interface{}, d time.Duration) error {
// 获取这个值
_, getrawerr := local_cache.getRaw(key)
if getrawerr == nil {
return core.CacheExist
}
// 设置值
_, errs := local_cache.set(key, value, d)
if errs != nil {
return errs
}
return nil
}
/**
* 修改值 , 不存在则报错
*/
func (local_cache *localCache) Replace(key string, value interface{}, d time.Duration) error {
// 获取这个值
_, getrawerr := local_cache.getRaw(key)
if getrawerr != nil {
return getrawerr
}
// 设置值
_, errs := local_cache.set(key, value, d)
if errs != nil {
return errs
}
return nil
}
/**
* 清空所有缓存
*/
func (local_cache *localCache) Flush() {
// 删除
local_cache.SM.Lock()
os.RemoveAll(local_cache.config.Path)
local_cache.SM.Unlock()
}
/**
* 清空单个缓存
*/
func (local_cache *localCache) Delete(key string) error {
// 获取缓存文件路径
filepath := local_cache.getCacheKey(key)
// 检测文件是否存在
_, err := os.Stat(filepath)
if err != nil {
// 文件不存在,输出
return core.NoCacheFile
}
// 删除
local_cache.delete(filepath)
return nil
}
/**
* 判断缓存是否存在
*/
func (local_cache *localCache) Has(key string) bool {
// 获取数据
_, err := local_cache.getRaw(key)
if err != nil {
return false
}
return true
}
//----------------------------------
// 实现 CacheInterface 接口 end
//----------------------------------
// 获取一个值
func (localCache *localCache) getRaw(key string) (interface{}, error) {
// 获取缓存文件路径
filepath := localCache.getCacheKey(key)
// 检测文件是否存在
_, err := os.Stat(filepath)
if err != nil {
// 文件不存在,输出
return nil, core.NoCacheFile
}
// 打开文件
f, err := os.Open(filepath)
if err != nil {
// 文件打开错误
return nil, core.OpenCacheFileFail
}
defer f.Close()
localCache.Cache.SM.RLock()
// 创建一个gob解码器
D := gob.NewDecoder(f)
// 注册 gob 会出现的类型
for _, v := range localCache.config.BogRegister {
// gob注册类型,自定义的类型必须先注册
gob.Register(v)
}
// 创建一个item 存储 gob解码出来的数据
value := core.Item{}
// 解码
err = D.Decode(&value)
if err != nil {
return nil, err
}
// 解锁
localCache.SM.RUnlock()
// 关闭
f.Close()
// 有value
if value.Expire != int64(localCache.NoExpire) {
// 有过期时间
if value.Expire < time.Now().UnixNano() {
// 过期 删除文件
localCache.delete(filepath)
return nil, core.CacheExpire
}
}
return value.Value, nil
}
// 过期删除
func (localCache *localCache) delete(filepath string) {
localCache.SM.Lock()
removeFile(filepath)
localCache.SM.Unlock()
}
// 获取cacheKey
func (local_cache *localCache) getCacheKey(key string) string {
// MD5 加密
h := md5.New()
h.Write([]byte(key))
md5 := hex.EncodeToString(h.Sum([]byte(local_cache.Prefix)))
// 子目录
filepath := md5[0:2] + "/" + md5[2:] + ".gob"
if local_cache.Prefix != "" {
filepath = local_cache.Prefix + "/" + md5[0:2] + "/" + local_cache.Prefix + md5[2:] + ".gob"
}
return local_cache.config.Path + "/" + filepath
}
// 设置
func (local_cache *localCache) set(key string, value interface{}, d time.Duration) (bool, error) {
// 获取key的缓存目录
filepath := local_cache.getCacheKey(key)
// 文件夹不存在,创建文件夹
filepath_arr := strings.Split(filepath, "/") // 根据“/” 截断
// 获取数组程度
length := len(filepath_arr)
// 判断文件是否存在
_, err := os.Stat(filepath)
if err != nil {
// 文件可能
// 判断文件夹是否存在
if os.IsNotExist(err) {
// 文件夹路径
path := strings.Join(filepath_arr[:length-1], "/")
err = os.MkdirAll(path, os.ModePerm)
if err != nil {
return false, err
}
} else {
return false, err
}
}
// 过期时间设置
var expire int64 = 0
if d == local_cache.NoExpire {
expire = 0
} else {
expire = time.Now().Add(d).UnixNano()
}
// item对象
it := core.Item{
Value: value,
Expire: expire,
}
// 打开文件
fs, _ := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE, 0777)
defer fs.Close()
// 加 互斥锁
local_cache.SM.Lock()
// 解 互斥锁
defer local_cache.SM.Unlock()
//写
enc := gob.NewEncoder(fs)
// 这里必须注册value的类型
gob.Register(value)
// 注册 gob 会出现的类型
for _, v := range local_cache.config.BogRegister {
// gob注册类型,自定义的类型必须先注册
gob.Register(v)
}
if err := enc.Encode(it); err != nil {
return false, err
}
return true, nil
}
func removeFile(filepath string) {
err := os.Remove(filepath)
if err == nil {
// 删除成功,再看看文件夹是否为空,为空接着删除
pathtemp, _ := path.Split(filepath)
removeFile(pathtemp[:len(pathtemp)-1])
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/yelhjt/gocache.git
git@gitee.com:yelhjt/gocache.git
yelhjt
gocache
gocache
v1.1.0

搜索帮助