go實現(xiàn)一個內(nèi)存緩存系統(tǒng)的示例代碼
更新時間:2024年10月18日 10:43:55 作者:Monkey@
本文主要介紹了go實現(xiàn)一個內(nèi)存緩存系統(tǒng)的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
面試內(nèi)容:
- 支持設定過期時間,精度到秒
- 支持設定最大內(nèi)存,當內(nèi)存超出時做出合適的處理
- 支持并發(fā)安全
- 要求按照以下接口實現(xiàn)
SetMemory(size string) bool
Set(key string, val interface{}, expire time.Duration) bool
Get(key string) (interface{}, bool)
Del(key string) bool
Exists(key string) bool
Flush() bool
Keys() int64下面為具體實現(xiàn)代碼:
接口
package cache
import "time"
type Cache interface {
SetMemory(size string) bool
Set(key string, val interface{}, expire time.Duration) bool
Get(key string) (interface{}, bool)
Del(key string) bool
Exists(key string) bool
Flush() bool
Keys() int64
}實現(xiàn)類
package cache
import (
"fmt"
"sync"
"time"
)
type MemCache struct {
//最大內(nèi)存
maxMemorySize int64
// 當前已使用的內(nèi)存
currMemorySize int64
// 最大內(nèi)存字符串表示
maxMemorySizeStr string
// 緩存鍵值對
values map[string]*memCacheValue
// 讀寫鎖
lock sync.RWMutex
//設置清除過期緩存的時間間隔
clearExpireTime time.Duration
}
type memCacheValue struct {
//value 值
val interface{}
// 過期時間
expireTime time.Time
//有效時間
expire time.Duration
//value 大小
size int64
}
func NewMemCache() Cache {
mc := &MemCache{
clearExpireTime: time.Second * 10,
values: make(map[string]*memCacheValue),
}
go mc.clearExpireItm()
return mc
}
// SetMemory size 1KB 100KB 1M 2M 1GB
func (mc *MemCache) SetMemory(size string) bool {
mc.maxMemorySize, mc.maxMemorySizeStr = ParseSize(size)
return true
}
// Set 設置緩存
func (mc *MemCache) Set(key string, val interface{}, expire time.Duration) bool {
mc.lock.Lock()
defer mc.lock.Unlock()
v := &memCacheValue{val: val, expireTime: time.Now().Add(expire),
expire: expire,
size: GetValSize(val)}
//mc.values[key] = v
mc.del(key)
mc.add(key, v)
if mc.currMemorySize > mc.maxMemorySize {
mc.del(key)
panic(fmt.Sprintf("max memory size %d", mc.maxMemorySize))
}
return true
}
func (mc *MemCache) get(key string) (*memCacheValue, bool) {
val, ok := mc.values[key]
return val, ok
}
func (mc *MemCache) del(key string) {
tmp, ok := mc.get(key)
if ok && tmp != nil {
mc.currMemorySize -= tmp.size
delete(mc.values, key)
}
}
func (mc *MemCache) add(key string, val *memCacheValue) {
mc.values[key] = val
mc.currMemorySize += val.size
}
// Get 獲取緩存值
func (mc *MemCache) Get(key string) (interface{}, bool) {
mc.lock.RLock()
defer mc.lock.RUnlock()
mcv, ok := mc.get(key)
if ok {
if mcv.expire != 0 && mcv.expireTime.Before(time.Now()) {
mc.del(key)
return nil, false
}
return mcv.val, ok
}
return nil, false
}
// Del 刪除緩存值
func (mc *MemCache) Del(key string) bool {
mc.lock.Lock()
defer mc.lock.Unlock()
mc.del(key)
return true
}
func (mc *MemCache) Exists(key string) bool {
mc.lock.RLock()
defer mc.lock.RUnlock()
_, ok := mc.get(key)
return ok
}
func (mc *MemCache) Flush() bool {
mc.lock.Lock()
defer mc.lock.Unlock()
mc.values = make(map[string]*memCacheValue, 0)
mc.currMemorySize = 0
return true
}
func (mc *MemCache) Keys() int64 {
mc.lock.RLock()
defer mc.lock.RUnlock()
return int64(len(mc.values))
}
func (mc *MemCache) clearExpireItm() {
ticker := time.NewTicker(mc.clearExpireTime)
defer ticker.Stop()
for {
select {
case <-ticker.C:
for key, v := range mc.values {
if v.expire != 0 && time.Now().After(v.expireTime) {
mc.lock.Lock()
mc.del(key)
mc.lock.Unlock()
}
}
}
}
}
//
//var Cache = NewMemCache()
//
//func Set(key string, val interface{}) bool {
//
// return false
//}
工具類
package cache
import (
"log"
"regexp"
"strconv"
"strings"
)
const (
B = 1 << (iota * 10)
KB
MB
GB
TB
PB
)
func ParseSize(size string) (int64, string) {
//默認大小為 100M
re, _ := regexp.Compile("[0-9]+")
unit := string(re.ReplaceAll([]byte(size), []byte("")))
num, _ := strconv.ParseInt(strings.Replace(size, unit, "", 1), 10, 64)
unit = strings.ToUpper(unit)
var byteNum int64 = 0
switch unit {
case "B":
byteNum = num
break
case "KB":
byteNum = num * KB
break
case "MB":
byteNum = num * MB
break
case "GB":
byteNum = num * GB
break
case "TB":
byteNum = num * TB
break
case "PB":
byteNum = num * PB
break
default:
num = 0
byteNum = 0
}
if num == 0 {
log.Println("ParseSize 僅支持B,KB,MB,GB,TB,PB")
num = 100 * MB
byteNum = num
unit = "MB"
}
sizeStr := strconv.FormatInt(num, 10) + unit
return byteNum, sizeStr
}
func GetValSize(val interface{}) int64 {
return 0
}
代理類
package server
import (
"go_lang_pro/cache"
"time"
)
type cacheServer struct {
memCache cache.Cache
}
func NewMemoryCache() *cacheServer {
return &cacheServer{
memCache: cache.NewMemCache(),
}
}
func (cs *cacheServer) SetMemory(size string) bool {
return cs.memCache.SetMemory(size)
}
func (cs *cacheServer) Set(key string, val interface{}, expire ...time.Duration) bool {
expirets := time.Second * 0
if len(expire) > 0 {
expirets = expire[0]
}
return cs.memCache.Set(key, val, expirets)
}
func (cs *cacheServer) Get(key string) (interface{}, bool) {
return cs.memCache.Get(key)
}
func (cs *cacheServer) Del(key string) bool {
return cs.memCache.Del(key)
}
func (cs *cacheServer) Exists(key string) bool {
return cs.memCache.Exists(key)
}
func (cs *cacheServer) Flush() bool {
return cs.memCache.Flush()
}
func (cs *cacheServer) Keys() int64 {
return cs.memCache.Keys()
}
main 方法
package main
import (
"go_lang_pro/cache"
"time"
)
func main() {
cache := cache.NewMemCache()
cache.SetMemory("100MB")
cache.Set("int", 1, time.Second)
cache.Set("bool", false, time.Second)
cache.Set("data", map[string]interface{}{"a": 1}, time.Second)
cache.Get("int")
cache.Del("int")
cache.Flush()
cache.Keys()
}到此這篇關于go實現(xiàn)一個內(nèi)存緩存系統(tǒng)的示例代碼的文章就介紹到這了,更多相關go 內(nèi)存緩存系統(tǒng)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
使用Golang創(chuàng)建單獨的WebSocket會話
WebSocket是一種在Web開發(fā)中非常常見的通信協(xié)議,它提供了雙向、持久的連接,適用于實時數(shù)據(jù)傳輸和實時通信場景,本文將介紹如何使用 Golang 創(chuàng)建單獨的 WebSocket 會話,包括建立連接、消息傳遞和關閉連接等操作,需要的朋友可以參考下2023-12-12
Go語言中三個輸入函數(shù)(scanf,scan,scanln)的區(qū)別解析
本文詳細介紹了Go語言中三個輸入函數(shù)Scanf、Scan和Scanln的區(qū)別,包括用法、功能和輸入終止條件等,本文給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧2024-10-10

