zoukankan      html  css  js  c++  java
  • 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]
    ", item, topx)
    }
    stringsValue, _ := redis.Strings(c1.Do("HMGET", "Top1", "BookName", "Author"))
    fmt.Printf("hmget:%+v
    ", 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)))
    

      

  • 相关阅读:
    jquery笔记(常用技术)
    AutoUpgraderPro 4.X美化版 源码及Demo程序
    读写Unicode和UTF8格式文件
    AutoUpgraderPro 4.X美化版 源码及Demo程序
    买了两套无线键鼠套装
    今天做了一回黑客
    AutoUpgraderPro Ver 4.1.1带源码美化版
    Delphi虚拟键码对照表
    Delphi虚拟键码对照表
    读写Unicode和UTF8格式文件
  • 原文地址:https://www.cnblogs.com/gwyy/p/13289126.html
Copyright © 2011-2022 走看看