当前位置: 代码网 > it编程>前端脚本>Golang > go实现一个内存缓存系统的示例代码

go实现一个内存缓存系统的示例代码

2024年11月03日 Golang 我要评论
面试内容:支持设定过期时间,精度到秒支持设定最大内存,当内存超出时做出合适的处理支持并发安全要求按照以下接口实现setmemory(size string) boolset(key string, v

面试内容:

  • 支持设定过期时间,精度到秒
  • 支持设定最大内存,当内存超出时做出合适的处理
  • 支持并发安全
  • 要求按照以下接口实现
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

下面为具体实现代码:

接口

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
}

实现类

package cache

import (
	"fmt"
	"sync"
	"time"
)

type memcache struct {
	//最大内存
	maxmemorysize int64
	// 当前已使用的内存
	currmemorysize int64
	// 最大内存字符串表示
	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实现一个内存缓存系统的示例代码的文章就介绍到这了,更多相关go 内存缓存系统内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网! 

(0)

相关文章:

  • Go语言中的通道chan使用指南

    Go语言中的通道chan使用指南

    go 语言的通道(chan)是实现并发编程的核心工具之一,它为 goroutine 之间的通信提供了一种简单而高效的方式。在这篇文章中,我们将深入探讨通道的使用... [阅读全文]
  • Go语言实现支付宝支付与退款详解

    Go语言实现支付宝支付与退款详解

    在当今数字支付的时代,移动支付已经成为各行各业的主流选择。支付宝作为中国最大的支付平台之一,提供了丰富的支付和退款api,供开发者集成到各种应用中。上期我已经介... [阅读全文]
  • GO语言中ni,零值与空结构体的使用

    GO语言中ni,零值与空结构体的使用

    go语言的初学者,特别是java开发者新学习go语言,对于一些和java类似但是又有差异的概念很容易混淆,比如说go中的零值,nil 和 空结构体。本文就来详细... [阅读全文]
  • Go语言中的网络编程实现方式

    Go语言中的网络编程实现方式

    引言go语言作为一种简洁而强大的编程语言,在网络编程方面表现尤为出色。其内置的net包提供了丰富的网络i/o基础设施,支持tcp、udp协议,以及dns解析等功... [阅读全文]
  • Go语言Seeker接口与文件断点续传实战教程

    seeker接口在现代软件开发中,高效的输入输出(i/o)操作是提高程序性能的关键之一。特别是在处理大量数据时,i/o操作的效率直接影响到应用程序的响应速度和用户体验。go语言标准…

    2024年11月03日 前端脚本
  • Go语言内建函数len的使用

    Go语言内建函数len的使用

    在 go 语言中,len 是一个非常常用的内建函数,它用于获取各种数据类型的长度或大小。掌握 len 的使用方法,可以帮助我们更高效地处理数据结构。本文将详细介... [阅读全文]

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com