Go语言实现Redis客户端

        这几天心血来潮,用Go写了一个Redis的简易版的客户端。主要参考了Python的redis-py和beego作者写的goredis。

       1、 主要特性

        1、默认使用连接池,默认大小为4,即从连接池中取建立好的socket,避免浪费;

        2、事务。支持事务处理;

 

 2、 使用方法

1、安装

      go get github.com/haipersist/hredis


2、Usage:

	Host,Port,Password,Db := "127.0.0.1",6379,"hehe",0
    	redis,err := hredis.Redis(Host,Port,Password,Db)

    	defer redis.DisConnect()
    	result,err := redis.Get("haibo"))
    	_,err := redis.Set("hhh","haibo")
    	result,err := redis.Incr("h")
    	result,err := redis.Lrange("sf",0,3)
    	for _,v := range result{
    		fmt.Println(string(v))
    	}

 

3、软件包介绍

定义了几个结构体和接口:

(1)Connection


type Connection struct {
	Host           string
	Port           int
	Db             int
	Password       string
	Sock           net.Conn
}

一个基本的socket连接,该连接类似于Python的基类,实现基本的数据传送,接收,连接的建立等方法。

(2)ConnectionPool

type ConnectionPool interface {
	GetConn()               (net.Conn,error)
	PutConn(conn net.Conn)  error
	UsingConn()             []Connection
	ClosePoolConn()         []error
}

type RedisPool struct {
	pool         chan net.Conn
}

//set the size of the connecion pool is 4
const MAXCONNUM = 4



func (r *RedisPool) GetConn() (net.Conn,error) {
	// If the pool channel has created con,it return one,or else return nil.
	//the pool should keep full value,avoid it is blocked.
	//when new conn request comes before the first conn push back,and the chan has no value,it will be blocked until other conn
	//push back conn to the Pool
	if r.pool == nil {
		r.pool = make(chan net.Conn,MAXCONNUM)
		for i:=0;i<MAXCONNUM;i++ {
			r.pool <- nil
		}
	}
	c := <- r.pool
	if c == nil {
		return nil,RedisError("No created connection")
	}
	return c,nil
}

func(r *RedisPool) ClosePoolConn() []error {
	if r.pool == nil {
	   var errors []error
	   return  append(errors,nil)
	}
	e := make([]error,len(r.pool))
	sum,length := 1,len(r.pool)
	for c := range r.pool {
		if c != nil {
			err:= c.Close()
			if err != nil {
				fmt.Println(err)
				e = append(e,err)
			} else {
				fmt.Println("the con is closed")
			}
		}
		if sum==length {
			close(r.pool)
			break

		} else {
			sum++
		}
	}
	return e
}

func (r *RedisPool) PutConn(conn net.Conn) error{
	if len(r.pool) < MAXCONNUM {
		r.pool <- conn
		return nil
	}
	return RedisError("the Pool is Full,sorry")
}

连接池RedisPool主要是为了读写连接,用Go的channel。

当channel满了,就会阻塞,等待其他的地方读取。

(3)Client


type Client struct {
	//I create it seperately,just because I want to add some logical code for client.Connection implement basci logic method.
	//as for client,it's method looks like the basic redis-cli.
	//add some field for client api ,which is used by pubic
	Pool          ConnectionPool
	Connection
	Transaction   bool
}

client是实现Redis命令的结构体,也是对外的接口,实现了Redis的实际命令。通过client的Pool选择connection,通过connection进行基本数据读取和发送。

默认事务是关闭的,如果你想使用事务,你应该加入:

 redis.Transaction = true

当事务开启的时候,就不使用连接池了,就只使用单个socket来进行通信。

 

(4)创建函数

//The function is used to create Connection,it is one interface between conncetion and public.
// every user should use it to get one client first.
func Redis(host string,port int,password string,db int) (*Client,error) {
	//The function is used to create Connection,it is one interface between conncetion and pubpic.
	// every user should use it to get one client first.
	conn := Connection{
		Host:host,
		Port:port,
		Db:db,
		Password:password,
		Sock:nil,
	}
	client := &Client{
		Connection:conn,
		Pool : &RedisPool{},
	}

	return client,nil
}

使用此包的方法是用上述的函数,最后返回的是Client结构体的引用。

具体的源码可见我的GitHub:hredis.

 

不过,我要说,我的这个客户端还不是特别完善,因为很多命令我还没写上,Redis命令有点多。此外,还不支持发布订阅,脚本等功能。后续再补吧。

--------EOF---------
本文微信分享/扫码阅读