Go实现简单的K-V存储

Go实现简单的K-V存储

使用Go实现简单的K-V存储,包括基本的增删改查功能。

本节代码将实现K-V存储的四个基本功能:

  • 添加新元素
  • 基于key删除已有的元素
  • 给定key查找对应value
  • 修改key对应的value

我们将这四个功能命名为ADD,DELETE,LOOKUP,CHANGE,完成这四个基本功能,你将会对K-V存储的实现有一个全面的了解。另外,当你输入STOP时整个程序就会停止,输入PRINT命令就会打印出当前K-V存储的所有内容。

本节的keyValue.go将分为5个代码段解释。

第一部分:

package main

import (
   "bufio"
   "fmt"
   "os"
   "strings"
)

type myElement struct {
   Name string
   SurName string
   Id string
}

var DATA = make(map[string]myElement)
复制代码

我们使用原生的Go map来实现K-V存储,因为内置的数据结构往往执行效率更高。map变量被声明为全局变量,其k为string类型,v为myElement类型,myElement是自定义的结构体。

第二部分代码:

func ADD(k string,n myElement) bool {
   if k == "" {
      return false
   }
   if LOOKUP(k) == nil {
      DATA[k] = n
      return true
   }
   return false
}

func DELETE(k string) bool {
   if LOOKUP(k) != nil {
      delete(DATA, k)
      return true
   }
   return false
}
复制代码

这部分代码实现了命令行ADD和DELETE,用户在执行ADD命令时,如果没有携带足够的参数,我们要保证该操作不会失败,意味着myElement中对应的字段为空字符串。然而如果你要添加的key已经存在了,就会报错(K-V存储不允许重复key出现)而不是修改对应的值。

第三部分代码:

func LOOKUP(k string) *myElement  {
   _, ok := DATA[k]
   if ok {
      n := DATA[k]
      return &n
   } else {
      return nil
   }
}

func CHANGE(k string, n myElement) bool {
   DATA[k] = n
   return true
}

func PRINT()  {
   for k, v := range DATA {
      fmt.Printf("key: %s value: %v",k,v)
   }
}
复制代码

该代码段实现了LOOKUP与CHANGE功能,如果你要修改的key不存储,程序会自动将其存储。

PRINT命令能够打印出目前所有K-V存储的内容。

第四部分代码:

func main() {
   scanner := bufio.NewScanner(os.Stdin)
   for scanner.Scan() {
      text := scanner.Text()
      text = strings.TrimSpace(text)
      tokens := strings.Fields(text)

      switch len(tokens) {
      case 0:
         continue
      case 1:
         tokens = append(tokens,"")
         tokens = append(tokens,"")
         tokens = append(tokens,"")
         tokens = append(tokens,"")
      case 2:
         tokens = append(tokens,"")
         tokens = append(tokens,"")
         tokens = append(tokens,"")
      case 3:
         tokens = append(tokens,"")
         tokens = append(tokens,"")
      case 4:
         tokens = append(tokens,"")
      
      }
复制代码

该部分代码读取用户的输入。首先,for循环将保证程序一直等待用户的输入,接下来使用tokens切片保证至少有5个元素的输入,即使只有ADD命令需要5个参数。如果用户不想在使用ADD命令时出现空字符串值,就需要这样输入:ADD aKey Field1 Field2 Field3。

最后一部分代码:

switch tokens[0] {
      case "PRINT":
         PRINT()
      case "STOP":
         return
      case "DELETE":
         if !DELETE(tokens[1]) {
            fmt.Println("Delete operations failed")
         }
      case "ADD":
         n := myElement{tokens[2],tokens[3],tokens[4]}
         if !ADD(tokens[1],n) {
            fmt.Println("Add operation failed")
         }
      case "LOOKUP":
         n := LOOKUP(tokens[1])
         if n != nil {
            fmt.Printf("%v\n",n)
         }

      case "CHANGE":
         n := myElement{tokens[2],tokens[3],tokens[4]}
         if !CHANGE(tokens[1],n) {
            fmt.Println("Update operation failed")
         }

      default:
         fmt.Println("Unknown command - please try again!")

      }
   }
}
复制代码

这部分代码处理用户的输入。switch的使用使得程序的逻辑设计看上去十分清晰,能够将程序员从冗余的if...else中拯救出来。

执行keyValue.go得到如下输出:

$ go run keyValue.go
UNKNOWN
Unknown command - please try again!

ADD 123 1 2 3
ADD 234 2 3 4
ADD 234
Add operation failed
ADD 345
PRINT
key: 123 value: {1 2 3}key: 234 value: {2 3 4}key: 345 value: {  }
CHANGE 345 3 4 5
PRINT
key: 345 value: {3 4 5}key: 123 value: {1 2 3}key: 234 value: {2 3 4}
DELETE 345
PRINT
key: 123 value: {1 2 3}key: 234 value: {2 3 4}
ADD 567 -5 -6 -7
PRINT
key: 123 value: {1 2 3}key: 234 value: {2 3 4}key: 567 value: {-5 -6 -7}
CHANGE 567
PRINT
key: 567 value: {  }key: 123 value: {1 2 3}key: 234 value: {2 3 4}  
STOP
复制代码

本文节选自Mastring_Go_ZH_CN

查看并运行文中代码

戳我完整阅读本书

戳我提出你的建议

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值