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---------
微信分享/微信扫码阅读
微信分享/微信扫码阅读