专栏首页roseduan写字的地方使用 Go 语言写一个数据库—5 命令行

使用 Go 语言写一个数据库—5 命令行

Hello 大家好,我是 roseduan,上一次给大家分享了 rosedb 项目当中所涉及到的一些数据结构,有链表、哈希表、跳表、有序集合,内容比较的硬核,你可以温习一下前面的几篇文章:

使用 Go 语言写一个数据库—4 数据结构

使用 Go 语言写一个数据库—3 数据库操作

使用 Go 语言写一个数据库—2 基本数据操作

使用 Go 语言写一个数据库—1 基本结构


今天的内容比较轻松,相信你一定可以完全掌握,参考视频在文章的底部。

我们常常使用 redis cli 来操作 redis ,比如 set、get 等等,那你知道它是怎么实现的吗?

这里我以 rosedb 为例,为你实现一个具备类似功能的命令行操作。首先来看一下完成后的效果示例:

在项目 rosedb/cmd/server 下面,有一个 main.go ,使用 go run main.go 命令来启动它:

然后在 rosedb/cmd/cli 下面,同样执行 go run main.go 来启动一个客户端,启动完成之后,就能够进行命令操作了,比如 set、get 等等:


接下来再看具体的实现,其实也比较简单,分为了两部分,服务端和客户端。

服务端

服务端的本质,就是启动一个 TCP 服务器,监听一个端口,主要代码如下:

func (s *Server) Listen(addr string) {
  var err error
  // 启动 TCP 服务器
  s.listener, err = net.Listen("tcp", addr)
  if err != nil {
    log.Printf("tcp listen err: %+v\n", err)
    return
  }

  log.Println("rosedb is running, ready to accept connections.")
  // 获取客户端的连接
  for {
    select {
    case <-s.done:
      return
    default:
      conn, err := s.listener.Accept()
      if err != nil {
        continue
      }
      // 处理连接
      go s.handleConn(conn)
    }
  }
}

服务端还做一件事情,就是获取客户端的连接,然后取出命令执行,并获取到执行的结果。

获取到结果之后,再返回到客户端,你可以看这个 handleConn 方法:

func (s *Server) handleConn(conn net.Conn) {
  defer conn.Close()
  for {
    // ...
    
    // 读取客户端的数据
    size := binary.BigEndian.Uint32(b[:4])
    if size > 0 {
      data := make([]byte, size)
      _, err := bufReader.Read(data)
      if err != nil {
        log.Printf("read cmd data err: %+v\n", err)
        break
      }

      // 执行命令,获取到结果
      cmdAndArgs := reg.FindAllString(string(data), -1)
      reply := s.handleCmd(cmdAndArgs[0], cmdAndArgs[1:])
      info := wrapReplyInfo(reply)
      
      // 将结果写回到客户端
      _, err = conn.Write(info)
      if err != nil {
        log.Printf("write reply err: %+v\n", err)
      }
    }
  }
}

客户端

客户端的工作,就是与服务端建立连接,然后获取用户的输入,并且传到服务端。

然后从服务端获取到运行的结果,并将结果打印出来,关键代码如下:

func main() {
  flag.Parse()

  addr := fmt.Sprintf("%s:%d", *host, *port)
  // 连接到服务器
  conn, err := net.Dial("tcp", addr)
  if err != nil {
    log.Println("tcp dial err: ", err)
    return
  }
  // ... 不重要的代码就忽略了
  
  // 命令数据传到服务端
      wInfo := wrapCmdInfo(cmd)
      _, err := conn.Write(wInfo)
      if err != nil {
        fmt.Println(err)
      }

  // 获取服务端的结果,并打印出来
      reply := readReply(conn)
      fmt.Println(reply)
    }
  }
}

这就是全部的实现了,是不是非常简单呢?当然我目前实现的这个版本,还是比较简陋的,很多命令都还没有支持,可完善的地方还是挺多的。

视频参考


题图:from wallheaven.cc

本文分享自微信公众号 - roseduan写字的地方(rose_duan),作者:roseduan

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-05-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用 Go 语言写一个数据库—3 数据库操作

    在前面的两篇文章当中,我给大家介绍了 rosedb 的基础结构,以及基本的数据操作流程。

    roseduan
  • 使用 Go 语言写一个数据库—4 数据结构

    前面几篇文章,我已经对 rosedb 有了一定的讲解了,如果还没有看前面的内容,请先看一下之前的内容,这样你才能更好的理解本篇文章的内容。

    roseduan
  • 使用 Go 语言写一个数据库—2 基本数据操作

    上一次给大家介绍了 rosedb 的基本结构:使用 Go 语言写一个数据库—1 基本结构

    roseduan
  • 使用 Go 语言写一个数据库—6 完结撒花

    Hello 大家好,我是 roseduan,前面的几篇文章,我已经讲述了 rosedb 最基础也是最核心的知识,如果你没有印象的话,可以温习一下:

    roseduan
  • Golang 命令

    go buildgo build 命令用于编译我们指定的源码文件或代码包以及它们的依赖包。go build [-o output] [-i] [build fl...

    李海彬
  • 从零开始创建一个基于Go语言的web service

    20个小时的时间能干什么?也许浑浑噩噩就过去了,也许能看一些书、做一些工作、读几篇博客、再写个一两篇博客,等等。而黑客马拉松(HackAthon),其实是一种自...

    李海彬
  • Go 中的 gRPC 入门详解

    golang-grpc 包提供了 gRPC 相关的代码库,通过这个库我们可以创建 gRPC 服务或客户端,首先需要安装他。

    痴者工良
  • [GO语言基础] 二.编译运行、语法规范、注释转义及API标准库知识普及

    作为网络安全初学者,会遇到采用Go语言开发的恶意样本。因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识;另一方面是分享与读者,希...

    Eastmount
  • Go语言核心36讲(导读)--学习笔记

    Go 程序可以在装有 Windows、Linux、FreeBSD 等操作系统的服务器上运行,并用于提供基础软件支撑、API 服务、Web 服务、网页服务等等。

    郑子铭
  • 《Go语言入门经典》13~15章读书笔记

    Go程序以package语句打头。main包是一种特殊的包,其特殊之处在于不能导入。对main包的唯一要求是,必须声明一个main函数,这个函数不接受任何参数且...

    跑马溜溜的球
  • Go语言环境搭建详解(2020版)

    最近写了很多Go语言的原创文章,其中Go语言实战系列30篇,近15W字,还有最近更新的Go经典库系列,不过通过大家的咨询来看,还是想要一些入门的知识,这一篇文章...

    飞雪无情
  • GO笔记之GO命令快速体验

    本文将在所能及的范围内,尽量地介绍GO提供的所有命令,从而实现对它们有个整体的认识。

    波罗学
  • Golang学习笔记汇总

    对于 go 的入门学习,我比较推荐两本书:《Go程序设计语言》by Alan.A.A.Donowan、《go语言编程》by 许世伟 吕桂华。《Go程序设计语言》...

    twowinter
  • Python和Go语言都这么火,哪个更适合你?

    在本文中,我们探讨了 Python 和 Go 这两种世界上最流行的编程语言的差异、相似之处和用例。 从对两者的快速比较开始,然后看看它们在可读性、速度、易学性等...

    TSINGSEE青犀视频
  • 这一次,我拒绝了Python,选择了Go

    最近,我用一个以 Go 语言为后端的软件,实现了一个人脸识别项目。它能够识别出上传照片中的人像 (如流行歌手)是谁。这听起来不错,我决定试一下也给你们介绍一下项...

    AI科技大本营
  • [日常] Go语言圣经--结构体,JSON习题

    2.通常一行对应一个结构体成员,成员的名字在前类型在后,不过如果相邻的成员类型如果相同的话可以被合并到一行

    陶士涵
  • 优雅的go语言--入门篇

        2.所有归档文件都会被存放在pkg目录下的平台相关目录中,同样以代码包为组织形式

    房上的猫
  • 在Go中使用Protobuf

    本教程使用proto3版本的protocol buffer语言,提供了一个基本的在Go程序中使用protocol buffer的介绍。通过创建一个简单的示例应用...

    KevinYan
  • 《快学 Go 语言》第 16 课 —— 包管理 GOPATH 和 Vendor

    到目前位置我们一直在编写单文件代码,只有一个 main.go 文件。本节我们要开始朝完整的项目结构迈进,需要使用 Go 语言的模块管理功能来组织很多的代码文件。

    老钱

扫码关注云+社区

领取腾讯云代金券