0%

通过Go+Map写k-v数据库(SET-GET简单实现磁盘存储版)

通过实现一个简单的K–V存储数据库,学习Go语言(三)

作为数据库我们需要将键值存储的数据保存在磁盘上,以及如何在下一次启动应用程序时将其加载到内存。

我们准备创建两个新函数,save()保存数据到磁盘,load()从磁盘加载数据。

将数据转换为字节流的过程称为序列化。读取数据文件并将其转换为对象的过程称为反序列化。

encoding/gob标准Go包将用于程序中。它将有助于序列化和反序列化过程。

encoding/gob包使用gob格式存储其数据。这种格式的官方名称是流编码。

gob格式的好处是,Go完成了所有的繁琐工作,因此你不必担心编码和解码阶段。

package main

import (
	"bufio"
	"encoding/gob"
	"fmt"
	"os"
	"strings"
)

var DATA = map[string]string{}
var DATAFILE = "dataFile.gob"

//myRedis基础功能

func SET(key string, value string) {
	if _, ok := DATA[key]; !ok {
		DATA[key] = value
		//fmt.Println("set successful!")
	} else {
		fmt.Println("error: existence of this key!")
	}

}
func GET(key string) {
	if _, ok := DATA[key]; !ok {
		fmt.Println("error: not found this key!")
	} else {
		fmt.Printf("%s\n", DATA[key])
	}

}
func DELETE(key string) {
	if _, ok := DATA[key]; !ok {
		fmt.Println("error: not found this key!")
	} else {
		delete(DATA, key)
		//fmt.Println("delete successful!")
	}
}
func UPDATE(key string, value string) {
	if _, ok := DATA[key]; !ok {
		fmt.Println("error: not found this key!")
	} else {
		DATA[key] = value
		//fmt.Println("update successful!")
	}
}

func SHOW() {

	for k, v := range DATA {
		fmt.Printf("%s:%s\n", k, v)
	}
}

//数据持久化

//保存数据在磁盘上
func save() error {
	//去除原数据文件,保存为新数据文件
	err := os.Remove(DATAFILE)
	if err != nil {
		fmt.Println(err)
	}

	saveFile, err := os.Create(DATAFILE)
	if err != nil {
		fmt.Println("Cannot create", DATAFILE)
		return err
	}
	defer saveFile.Close()
	//序列化存储数据到文件
	encoder := gob.NewEncoder(saveFile)
	//转码数据
	err = encoder.Encode(DATA)
	fmt.Println(DATA, saveFile, DATAFILE)
	if err != nil {
		fmt.Println("Cannot save to", DATAFILE)
		return err
	}
	return nil
}

//启动应用时,加载数据

func load() error {
	loadFile, err := os.Open(DATAFILE)
	defer loadFile.Close()
	if err != nil {
		fmt.Println("Empty key/value store!")
		return err
	}

	//反序列化读取文件
	decoder := gob.NewDecoder(loadFile)
	//解码数据
	decoder.Decode(&DATA)
	return nil
}


func main() {
	//load File
	err := load()
	if err != nil {
		fmt.Println(err)
	}

	cmd := []string{}
	s := bufio.NewScanner(os.Stdin)
	for s.Scan() {
		text := s.Text()
		cmd = strings.Split(text, " ")
		//strings.TrimSpace()
		//strings.Fields()
		switch cmd[0] {
		case "SET":
			SET(cmd[1], cmd[2])
		case "GET":
			GET(cmd[1])
		case "SHOW":
			SHOW()
		case "DELETE":
			DELETE(cmd[1])
		case "UPDATE":
			UPDATE(cmd[1], cmd[2])
		case "STOP":
			err = save()
			if err != nil {
				fmt.Println(err)
			}
		default:
			fmt.Println("Unknown command - please try again!")
		}

	}

	//end to save file
	err = save()
	if err != nil {
		fmt.Println(err)
	}

}
-------------本文结束感谢您的阅读-------------
打赏一瓶矿泉水