GO实现内存数据库
前面我们实现了一个简单的回发Redis,这里我们要实现一个真正的Redis内核
实现底层Dict数据结构
新建一个datastruct文件夹,放一些我们要用的数据结构,比如Redis的核心起始就是一个map,再新建一个包实现这个map或者叫字典,字典的底层使用的就是map
dict.go
写一个Dict接口定义一些map要实现的功能,注意ForEach方法的入参是一个方法,把这个方法施加到全部k-v,和Range方法类似
// Consumer is used to traversal dict, if it returns false the traversal will be break
type Consumer func(key string, val interface{}) bool
// Dict is interface of a key-value data structure
type Dict interface {
Get(key string) (val interface{}, exists bool) //返回相应key对应的value和key是否存在
Len() int //字典中有多少个key - value键值对
Put(key string, val interface{}) (result int) //将key - value存进dict,存进去回复1,没有存进去回复0
PutIfAbsent(key string, val interface{}) (result int) //如果没有则存进对应的key - value
PutIfExists(key string, val interface{}) (result int) //如果有则修改对应的key - value
Remove(key string) (result int) //从字典中删除key - value
ForEach(consumer Consumer) //遍历整个字典,传入的是一个方法
Keys() []string //列出所有的key
RandomKeys(limit int) []string //随机列一定数量的键
RandomDistinctKeys(limit int) []string //随机返回一定数据量不重复的key
Clear() //清空字典
}
然后就是实现刚才写的接口
sync_dict.go文章来源:https://www.toymoban.com/news/detail-665540.html
首先是SyncDict结构体,他的成员只有一个就是sync.Map,然后写一个New方法,RandomKeys方法和RandomDistinctKeys方法实现逻辑上的区别是RandomKeys方法是在for循环里调用Range方法,Range方法里return false,每次for循环只调用一次Range方法,有可能遍历到相同的key,而RandomDistinctKeys方法是return true,直到计数器变量增加到limit时return false,Clear方法不用遍历map一个个删掉,只需要Make一个新的SyncDict,旧的SyncDict由GC做垃圾回收即可文章来源地址https://www.toymoban.com/news/detail-665540.html
// SyncDict wraps a map, it is not thread safe
type SyncDict struct {
m sync.Map
}
// MakeSyncDict makes a new map
func MakeSyncDict() *SyncDict {
return &SyncDict{}
}
// Get returns the binding value and whether the key is exist
func (dict *SyncDict) Get(key string) (val interface{}, exists bool) {
val, ok := dict.m.Load(key) //Load方法是sync.map的Get方法
return val, ok
}
// Len returns the number of dict
func (dict *SyncDict) Len() int {
lenth := 0
dict.m.Range(func(k, v interface{}) bool {
lenth++
return true
})
return lenth
}
// Put puts key value into dict and returns the number of new inserted key-value
func (dict *SyncDict) Put(key string, val interface{}) (result int) {
_, existed := dict.m.Load(key)
dict.m.Store(key, val)
if existed {
return 0 //仅修改,没有插入新的kv
}
return 1 //插入新的kv
}
// PutIfAbsent puts value if the key is not exists and returns the number of updated key-value
func (dict *SyncDict) PutIfAbsent(key string, val interface{}) (result int) {
_, existed := dict.m.Load(key)
if existed {
return 0
}
dict.m.Store(key, val)
return 1
}
// PutIfExists puts value if the key is exist and returns the number of inserted key-value
func (dict *SyncDict) PutIfExists(key string, val interface{}) (result int) {
_, existed := dict.m.Load(key)
if existed {
dict.m.Store(key, val)
return 1
}
return 0
}
// Remove removes the key and return the number of deleted key-value
func (dict *SyncDict) Remove(key string) (result int) {
_, existed := dict.m.Load(key)
dict.m.Delete(key)
if existed {
return 1
}
return 0
}
// Keys returns all keys in dict
func (dict *SyncDict) Keys() []string {
result := make([]string, dict.Len())
i := 0
dict.m.Range(func(key, value interface{}) bool {
result[i] = key.(string)
i++
return true
})
return result
}
// ForEach traversal the dict
func (dict *SyncDict) ForEach(consumer Consumer) {
di
到了这里,关于Go重写Redis中间件 - Go实现内存数据库的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!