golang 從零實現一個redis客戶端(一)最簡單的redis客戶端

目的

通過搭建一個高可用的redis客戶端來學習redis,go語言,以及go一些設計模式

參考資料

go-redis源碼

redis-3.0源碼

《redis設計與實現》

學習思路

循環漸進,從最簡單的一步步迭代

 

一個最簡單的能跑通的redis客戶端例子

package main

import (
        "fmt"
        "net"
        "strings"
)

type options struct {
        Network string
        Addr    string
}

func (p *options) init() {
        if p.Addr == "" {
                p.Addr = "127.0.0.1:6379"
        }
        if p.Network == "" {
                p.Network = "tcp"
        }
}

//redis struct
type redisClient struct {
        opt     options
        conn    net.Conn
        sendCmd string
        reply   string
}

func (c *redisClient) connect() {
        conn, err := net.Dial(c.opt.Network, c.opt.Addr)
        if err != nil {
                fmt.Println("connect err ", err)
        }
        c.conn = conn
}

func (c *redisClient) sendCommand(cmd string) string {
        c.formatCommand(cmd)
        c.write()
        return c.getReply()
}

func (c *redisClient) formatCommand(cmd string) {
        var protocl_cmd string
        cmd_argv := strings.Fields(cmd)
        protocl_cmd = fmt.Sprintf("*%d\r\n", len(cmd_argv))
        for _, arg := range cmd_argv {
                protocl_cmd += fmt.Sprintf("$%d\r\n", len(arg))
                protocl_cmd += arg
                protocl_cmd += "\r\n"
        }
        //redis服務器接受的命令協議
        fmt.Printf("%q\n", protocl_cmd)
        c.sendCmd = protocl_cmd
}
func (c *redisClient) write() {
        c.conn.Write([]byte(c.sendCmd))
        c.sendCmd = ""
}

func (c redisClient) getReply() string {
        byte_len := 1024 * 16
        reply := make([]byte, byte_len)
        //暫時簡化一次輸出完
        c.conn.Read(reply)
        return string(reply)
}

func NewClient(opt options) *redisClient {
        c := redisClient{
                opt: opt,
        }
        c.opt.init()
        c.connect()
        return &c
}

func main() {

        c := NewClient(options{
                Addr: "127.0.0.1:6379",
        })
        rep := c.sendCommand("set hello world")
        fmt.Println(rep)
}

上面這個例子,暫時沒考慮讀寫循環,錯誤處理,主要實現了發送redis服務器命令協議內容,以及客戶端連接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章