go操作redis


golang操作redis主要有兩個庫,go-redis和redigo。兩者操作都比較簡單,區別上redigo更像一個client執行各種操作都是通過Do函數去做的,redis-go對函數的封裝更好,相比之下redigo操作redis顯得有些繁瑣。但是官方更推薦redigo,所以項目中我使用了redigo。
redigo的使用入門可以去查godoc:http://godoc.org/github.com/garyburd/redigo/redis
 
引入包:github.com/gomodule/redigo/redis
 

連接redis:

有好幾種連接的方法:

//第一種連接方法
c1,err := redis.Dial("tcp","127.0.0.1:6379")
if err != nil {
   panic(err)
}
defer c1.Close()
//第二種連接方法 其實這個最后還是會調用Dial
c2,err := redis.DialURL("redis://127.0.0.1:6379")
if err != nil {
   panic(err)
}
defer c2.Close()

  

常用api:

//Send + Flush + Receive = Do
rec1,err := c1.Do("Get","gwyy")
fmt.Println(string(rec1.([]byte)))

c2.Send("Get","gwyy")
c2.Flush()
rec2,err := c2.Receive()
fmt.Println(string(rec2.([]byte)))

//set 永不過期
_,err = c1.Do("Set","xhc","xhc hahaha")
if err != nil {
   panic(err)
}
//5秒過期
_,err = c1.Do("Set","xhc1","xhc hahaha","EX",5)
if err != nil {
   panic(err)
}
//檢查key是否存在
is_key_exit,err := redis.Bool(c1.Do("EXISTS","gwyy"))
if err != nil {
   panic(err)
}
fmt.Println(is_key_exit)
//刪除一個key
_, err = c1.Do("DEL", "mykey")
if err != nil {
   fmt.Println("redis delelte failed:", err)
}
//設置過期時間
n, _ := c1.Do("EXPIRE", "xhc", 24*3600)
fmt.Println(n)

//list 操作
_,_ = c1.Do("lpush","mylist","redis")
_,_ = c1.Do("lpush","mylist","mongodb")
_,_ = c1.Do("lpush","mylist","mysql")
//​ value 將一組命令結果轉換為 []interface{}。如果err不等於nil,那么Values返回nil,err
values,_ := redis.Values(c1.Do("lrange","mylist","0","-1"))
for _,v := range values {
   fmt.Println(string(v.([]byte)))
}

  

Do傳參Args:

定義:type Args []interface{}
Args是幫助構造結構化值的命令參數,一般用在Hmset
type Book struct {
   BookName  string
   Author    string
   PageCount string
   Press     string
}
top1 := Book{
   BookName:  "Crazy golang",
   Author:    "Moon",
   PageCount: "600",
   Press:     "GoodBook",
}

if _, err := c1.Do("HMSET", redis.Args{}.Add("Top1").AddFlat(&top1)...); err != nil {
   fmt.Println(err)
}
topx := Book{}
for _, item := range []string{"Top1"} {
   value, _ := redis.Values(c1.Do("HGETALL", item))
    redis.ScanStruct(value, &topx)
   fmt.Printf("%s[%+v]\n", item, topx)
}
stringsValue, _ := redis.Strings(c1.Do("HMGET", "Top1", "BookName", "Author"))
fmt.Printf("hmget:%+v\n", stringsValue)

//普通命令也可以用args展開
dd := redis.Args{}.Add("aa11").AddFlat("bb")
c1.Do("Set",dd...)

//redis mget 兩種用法 args := redis.Args{} args = args.Add("gwyy").Add("pipe1").Add("aa11") //[[72 101 108 108 111 44 103 119 121 121] [49 49 49] [98 98]] //mget 默認會返回[]interface{} 如果直接拿來用 需要自己強轉一遍 rec1,err1 := c1.Do("MGET",args...) if err1 != nil {fmt.Println(err1)} for _,v:= range rec1.([]interface{}) { fmt.Println(string(v.([]byte))) } //可以用redis 封裝的 ByteSlices 直接幫你轉換 //[[72 101 108 108 111 44 103 119 121 121] [49 49 49] [98 98]] slice rec1,err1 := redis.ByteSlices(c1.Do("MGET",args...))

  

  

  

管道操作:

Send 向諒解的輸出緩沖中寫入命令, Flush將鏈接輸出緩沖清空並寫入服務端,Recevie按照FIFO 順序依次讀取服務器的響應。

//管道  Send  Flush Receive
//Send 向諒解的輸出緩沖中寫入命令, Flush將鏈接輸出緩沖清空並寫入服務端,Recevie按照FIFO 順序依次讀取服務器的響應
c1.Send("SET","pipe1","111")
c1.Send("GET","pipe1")
c1.Send("GET","xhc")
c1.Flush()
c1.Receive() //返回了 set
v,err :=  c1.Receive() //返回了get  pipe1
v1,err :=  c1.Receive() //返回了get xhc
fmt.Println(string(v.([]byte)))
fmt.Println(string(v1.([]byte)))
//Do方法組合了Send,Flush和 Receive方法。Do方法先寫入命令,然后清空輸出buffer,最后接收全部掛起響應包括Do方發出的命令的結果。
//如果任何響應中包含一個錯誤,Do返回錯誤。如果沒有錯誤,Do方法返回最后一個響應。

  

連接池:

在golang的項目中,若要頻繁的用redis(或者其他類似的NoSQL)來存取數據,最好用redigo自帶的池來管理連接。
不然的話,每當要操作redis時,建立連接,用完后再關閉,會導致大量的連接處於TIME_WAIT狀態(redis連接本質上就是tcp)。
注:TIME_WAIT,也叫TCP半連接狀態,會繼續占用本地端口。

var RedisClient *redis.Pool
RedisClient = &redis.Pool{
   //連接方法
   Dial:            func() (redis.Conn,error) {
      c,err := redis.Dial("tcp","127.0.0.1:6379")
      if err != nil {
         return nil,err
      }
      c.Do("SELECT",0)
      return c,nil
   },
   //DialContext:     nil,
   //TestOnBorrow:    nil,
   //最大的空閑連接數,表示即使沒有redis連接時依然可以保持N個空閑的連接,而不被清除,隨時處於待命狀態。
   MaxIdle:         1,
   //最大的激活連接數,表示同時最多有N個連接
   MaxActive:       10,
   //最大的空閑連接等待時間,超過此時間后,空閑連接將被關閉
   IdleTimeout:     180 * time.Second,
   //Wait:            false,
   //MaxConnLifetime: 0,
}
//拿到一個連接
c1 := RedisClient.Get()
defer c1.Close()
r,_ := c1.Do("GET","xhc")
fmt.Println(string(r.([]byte)))

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM