设为首页 加入收藏

TOP

GO实现Redis:GO实现内存数据库(3)(二)
2023-07-23 13:31:29 】 浏览:73
Tags:实现 Redis
ArgNumErrReply(cmdName) } fun := cmd.executor return fun(db, cmdLine[1:]) // 把 set k v 中的set切掉 } // 定长:set k v => arity=3; // 变长:exists k1 k2 k3 ... => arity=-2,表示参数>=2个 func validateArity(arity int, cmdArgs [][]byte) bool { argNum := len(cmdArgs) if arity >= 0 { return argNum == arity } return argNum >= -arity } func (db *DB) GetEntity(key string) (*database.DataEntity, bool) { raw, ok := db.data.Get(key) if !ok { return nil, false } entity, _ := raw.(*database.DataEntity) return entity, true } func (db *DB) PutEntity(key string, entity *database.DataEntity) int { return db.data.Put(key, entity) } func (db *DB) PutIfExists(key string, entity *database.DataEntity) int { return db.data.PutIfExists(key, entity) } func (db *DB) PutIfAbsent(key string, entity *database.DataEntity) int { return db.data.PutIfAbsent(key, entity) } func (db *DB) Remove(key string) { db.data.Remove(key) } func (db *DB) Removes(keys ...string) (deleted int) { deleted = 0 for _, key := range keys { _, exists := db.data.Get(key) if exists { db.Remove(key) deleted++ } } return deleted } func (db *DB) Flush() { db.data.Clear() }

实现Redis中的分数据库
ExecFunc:所有Redis的指令都写成这样的类型
validateArity方法:

  • 定长:set k v => arity=3;
  • 变长:exists k1 k2 k3 ... => arity=-2,表示参数>=2个

database/command.go

var cmdTable = make(map[string]*command)

type command struct {
   executor ExecFunc
   arity    int 
}

func RegisterCommand(name string, executor ExecFunc, arity int) {
   name = strings.ToLower(name)
   cmdTable[name] = &command{
      executor: executor,
      arity:    arity,
   }
}

command:每一个command结构体都是一个指令,例如ping,keys等等
arity:参数数量
cmdTable:记录所有指令和command结构体的关系
RegisterCommand:注册指令的实现,在程序

database/ping.go

func Ping(db *DB, args [][]byte) resp.Reply {
    if len(args) == 0 {
        return &reply.PongReply{}
    } else if len(args) == 1 {
        return reply.MakeStatusReply(string(args[0]))
    } else {
        return reply.MakeErrReply("ERR wrong number of arguments for 'ping' command")
    }
}

func init() {
    RegisterCommand("ping", Ping, 1)
}

init方法:在启动程序时就会调用这个方法,用于初始化

database/keys.go

// execDel:del k1 k2 k3 ...
func execDel(db *DB, args [][]byte) resp.Reply {
   keys := make([]string, len(args))
   for i, v := range args {
      keys[i] = string(v)
   }

   deleted := db.Removes(keys...)
   return reply.MakeIntReply(int64(deleted))
}

// execExists:exist k1 k2 k3 ...
func execExists(db *DB, args [][]byte) resp.Reply {
   result := int64(0)
   for _, arg := range args {
      key := string(arg)
      _, exists := db.GetEntity(key)
      if exists {
         result++
      }
   }
   return reply.MakeIntReply(result)
}

// execFlushDB:flushdb
func execFlushDB(db *DB, args [][]byte) resp.Reply {
   db.Flush()
   return &reply.OkReply{}
}

// execType:type k1
func execType(db *DB, args [][]byte) resp.Reply {
   key := string(args[0])
   entity, exists := db.GetEntity(key)
   if !exists {
      return reply.MakeStatusReply("none")
   }
   switch entity.Data.(type) {
   case []byte:
      return reply.MakeStatusReply("string")
   }
   return &reply.UnknownErrReply{}
}

// execRename:rename k1 k2
func execRename(db *DB, args [][]byte) resp.Reply {
   if len(args) != 2 {
      return reply.MakeErrReply("ERR wrong number of arguments for 'rename' command")
   }
   src := string(args[0])
   dest := string(args[1])
   
   entity, ok := db.GetEntity(src)
   if !ok {
      re
首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇「高频必考」Docker&K8S面试题和.. 下一篇Go语言入门2(流程控制,string)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目