226 lines
4.0 KiB
Go
226 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
"unsafe"
|
|
)
|
|
|
|
type CacheInterface interface {
|
|
// size: 1KB 100KB 1MB 2MB 1GB
|
|
SetMaxMemory(size string) error
|
|
|
|
// value写入缓存
|
|
Set(key string, val interface{}, expire time.Duration) error
|
|
|
|
// 根据key获取value
|
|
Get(key string) (interface{}, error)
|
|
|
|
// 删除key值
|
|
Del(key string) error
|
|
|
|
// 判断key是否存在
|
|
Exists(key string) (bool, error)
|
|
|
|
// 清空所有key
|
|
Flush() error
|
|
|
|
// 获取缓存中所有key的数量
|
|
Keys() int64
|
|
}
|
|
|
|
type Cache struct {
|
|
ObjectCount int64 // 缓存中对象数量
|
|
CurrentMemory int64 // 当前缓存占用内存大小
|
|
MaxMemory *int64 // 最大缓存内存大小
|
|
Storage map[string]interface{} // 缓存存储
|
|
}
|
|
|
|
/*
|
|
* 设置最大内存
|
|
* size: 1KB 100KB 1MB 2MB 1GB
|
|
*/
|
|
func (C *Cache) SetMaxMemory(size string) (err error) {
|
|
var (
|
|
gb bool = strings.Contains(size, "GB") || strings.Contains(size, "gb")
|
|
mb bool = strings.Contains(size, "MB") || strings.Contains(size, "mb")
|
|
kb bool = strings.Contains(size, "KB") || strings.Contains(size, "kb")
|
|
|
|
kilobyte int64 = 1024
|
|
megabyte int64 = 1024 * kilobyte
|
|
gigabyte int64 = 1024 * megabyte
|
|
|
|
sizeCount int64
|
|
|
|
errorHandling = func() (err error) {
|
|
return fmt.Errorf("set max memory error")
|
|
}
|
|
)
|
|
|
|
if len(size) <= 2 || (!gb && !mb && !kb) {
|
|
err = fmt.Errorf("max memory illegal")
|
|
return
|
|
}
|
|
|
|
if gb {
|
|
sizeCount, err = strconv.ParseInt(size[:len(size)-2], 10, 64)
|
|
if err != nil {
|
|
return errorHandling()
|
|
}
|
|
|
|
sizeCount *= gigabyte
|
|
C.MaxMemory = &sizeCount
|
|
}
|
|
|
|
if mb {
|
|
sizeCount, err = strconv.ParseInt(size[:len(size)-2], 10, 64)
|
|
if err != nil {
|
|
return errorHandling()
|
|
}
|
|
|
|
sizeCount *= megabyte
|
|
C.MaxMemory = &sizeCount
|
|
}
|
|
|
|
if kb {
|
|
sizeCount, err = strconv.ParseInt(size[:len(size)-2], 10, 64)
|
|
if err != nil {
|
|
return errorHandling()
|
|
}
|
|
|
|
sizeCount *= kilobyte
|
|
C.MaxMemory = &sizeCount
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
/*
|
|
* 设置缓存
|
|
* key: 缓存key
|
|
* val: 缓存value
|
|
* expire: 过期时间
|
|
*/
|
|
func (C *Cache) Set(key string, val interface{}, expire time.Duration) (err error) {
|
|
// 判断是否超过最大内存
|
|
valSize := unsafe.Sizeof(val)
|
|
if valSize+uintptr(C.CurrentMemory) > uintptr(*C.MaxMemory) {
|
|
return fmt.Errorf("exceed maximum memory, set failed")
|
|
}
|
|
|
|
// 设置缓存
|
|
C.Storage[key] = val
|
|
C.CurrentMemory += int64(valSize)
|
|
C.ObjectCount++
|
|
|
|
// 设置过期时间
|
|
go func() {
|
|
time.Sleep(expire)
|
|
C.Del(key)
|
|
}()
|
|
return
|
|
}
|
|
|
|
/*
|
|
* 获取缓存
|
|
* key: 缓存key
|
|
*/
|
|
func (C *Cache) Get(key string) (val interface{}, err error) {
|
|
var ok bool
|
|
if val, ok = C.Storage[key]; ok {
|
|
return
|
|
} else {
|
|
err = fmt.Errorf("key don't exists")
|
|
return
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 删除缓存
|
|
* key: 缓存key
|
|
*/
|
|
func (C *Cache) Del(key string) (err error) {
|
|
if val, ok := C.Storage[key]; ok {
|
|
delete(C.Storage, key)
|
|
C.ObjectCount--
|
|
|
|
valSize := unsafe.Sizeof(val)
|
|
*C.MaxMemory = C.CurrentMemory - int64(valSize)
|
|
return
|
|
} else {
|
|
return fmt.Errorf("key don't exists")
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 判断key是否存在
|
|
* key: 缓存key
|
|
*/
|
|
func (C *Cache) Exists(key string) (exist bool, err error) {
|
|
if _, ok := C.Storage[key]; ok {
|
|
exist = true
|
|
return
|
|
} else {
|
|
exist = false
|
|
return
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 清空所有缓存
|
|
*/
|
|
func (C *Cache) Flush() (err error) {
|
|
C.Storage = make(map[string]interface{})
|
|
C.ObjectCount = 0
|
|
C.CurrentMemory = 0
|
|
|
|
return
|
|
}
|
|
|
|
/*
|
|
* 获取缓存中所有key的数量
|
|
*/
|
|
func (C *Cache) Keys() (count int64) {
|
|
return C.ObjectCount
|
|
}
|
|
|
|
func main() {
|
|
cache := &Cache{
|
|
Storage: make(map[string]interface{}),
|
|
}
|
|
|
|
err := cache.SetMaxMemory("1gb")
|
|
if err != nil {
|
|
log.Fatal(err.Error())
|
|
return
|
|
}
|
|
|
|
err = cache.Set("hello", "world", 2*time.Second)
|
|
if err != nil {
|
|
log.Fatalln(err.Error())
|
|
return
|
|
}
|
|
|
|
result, err := cache.Get("hello")
|
|
if err != nil {
|
|
log.Fatalln(err.Error())
|
|
return
|
|
}
|
|
|
|
fmt.Println(result)
|
|
fmt.Println(cache.Exists("hello"))
|
|
fmt.Println(cache.Keys())
|
|
|
|
time.Sleep(3 * time.Second)
|
|
|
|
fmt.Println(cache.Exists("hello"))
|
|
fmt.Println(cache.Keys())
|
|
|
|
cache.Flush()
|
|
|
|
fmt.Println(cache)
|
|
}
|