• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Go语言基础之17--Redis基本操作

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

1.1 介绍

使用第三方的redis库, github.com/garyburd/redigo/redis

github地址:https://github.com/gomodule/redigo

下载:

go get github.com/garyburd/redigo

 

1.2 连接redis

package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func initRedis() (conn redis.Conn, err error) { //连接redis函数
    conn, err = redis.Dial("tcp", "127.0.0.1:6379") //传递协议、ip、端口
    if err != nil {
        fmt.Printf("conn redis failed, err:%v\n", err)
        return
    }
    fmt.Printf("connect redis successful!!!\n")
    return
}

func main() {
    conn, err := initRedis()
    if err != nil {
        return
    }
    defer conn.Close() //关闭连接
}

 执行结果:

二、redis开发

2.1 set操作

package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func initRedis() (conn redis.Conn, err error) { //连接redis函数
    conn, err = redis.Dial("tcp", "127.0.0.1:6379") //传递协议、ip、端口
    if err != nil {
        fmt.Printf("conn redis failed, err:%v\n", err)
        return
    }
    fmt.Printf("connect redis successful!!!\n")
    return
}

func testSetGet(conn redis.Conn) {
    key := "abc"
    _, err := conn.Do("set", key, "this is a test") //用do函数来进行redis命令操作
    if err != nil {
        fmt.Printf("set failed:%s\n", err)
        return
    }

    //reply, err := conn.Do("get", "abc") //get返回的是1个空接口,我们不知道里面内容到底什么类型,所以要做一次转换
    data, err := redis.String(conn.Do("get", key)) //因为我们知道存的是string,所以转换时是redis.string,如果存的是int,那就是redis.int
    if err != nil {
        fmt.Printf("get failed, err:%v\n", err)
        return
    }

    fmt.Printf("key:%s value:%s\n", key, data)
}

func main() {
    conn, err := initRedis()
    if err != nil {
        return
    }
    defer conn.Close() //关闭连接

    testSetGet(conn)
}

 执行结果:

2.2 hash表操作

hash表是把一类的数据聚合在一块。比如books表存的都是书籍相关的数据

package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func initRedis() (conn redis.Conn, err error) { //连接redis函数
    conn, err = redis.Dial("tcp", "127.0.0.1:6379") //传递协议、ip、端口
    if err != nil {
        fmt.Printf("conn redis failed, err:%v\n", err)
        return
    }
    fmt.Printf("connect redis successful!!!\n")
    return
}

func testHSetGet(conn redis.Conn) {
    key := "abc"
    _, err := conn.Do("hset", "books", key, "this is a test") //books是哈希表名 其中存的是一条条key-value
    if err != nil {
        fmt.Printf("set failed:%s\n", err)
        return
    }

    //reply, err := conn.Do("get", "abc")
    data, err := redis.String(conn.Do("hget", "books", key))
    if err != nil {
        fmt.Printf("get failed, err:%v\n", err)
        return
    }

    fmt.Printf("key:%s value:%s\n", key, data)
}

func main() {
    conn, err := initRedis()
    if err != nil {
        return
    }
    defer conn.Close() //关闭连接

    testHSetGet(conn)
}

执行结果:

2.3 mset操作

并发批量操作

package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func initRedis() (conn redis.Conn, err error) { //连接redis函数
    conn, err = redis.Dial("tcp", "127.0.0.1:6379") //传递协议、ip、端口
    if err != nil {
        fmt.Printf("conn redis failed, err:%v\n", err)
        return
    }
    fmt.Printf("connect redis successful!!!\n")
    return
}

func testMSetGet(conn redis.Conn) {
    key := "abc"
    key1 := "efg"
    _, err := conn.Do("mset", key, "this is a test", key1, "ksksksksks") //一次设置多个key
    if err != nil {
        fmt.Printf("set failed:%s\n", err)
        return
    }

    //reply, err := conn.Do("get", "abc")
    data, err := redis.Strings(conn.Do("mget", key, key1)) //一次读取多个 。返回的data是1个切片,这里用strings函数
    if err != nil {
        fmt.Printf("get failed, err:%v\n", err)
        return
    }
    for _, val := range data { //遍历出来
        fmt.Printf(" value:%s\n", val)
    }
}

func main() {
    conn, err := initRedis()
    if err != nil {
        return
    }
    defer conn.Close() //关闭连接

    testMSetGet(conn)
}

 执行结果:

2.4 设置过期时间

package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func initRedis() (conn redis.Conn, err error) { //连接redis函数
    conn, err = redis.Dial("tcp", "127.0.0.1:6379") //传递协议、ip、端口
    if err != nil {
        fmt.Printf("conn redis failed, err:%v\n", err)
        return
    }
    fmt.Printf("connect redis successful!!!\n")
    return
}

func testExpire(conn redis.Conn) {
    _, err := conn.Do("expire", "abc", 20)  //设置key为abc的过期时间为20s
    if err != nil {
        fmt.Println(err)
        return
    }
}

func main() {
    conn, err := initRedis()
    if err != nil {
        return
    }
    defer conn.Close() //关闭连接

    testExpire(conn)
}

 执行结果:

2.5 队列和栈操作

有4个方法:

lpush:左入队

rpush:右入队

lpop:左出队

rpop:右出队

队列:先进先出

栈:先进后出

 

队列实例:

package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func initRedis() (conn redis.Conn, err error) { //连接redis函数
    conn, err = redis.Dial("tcp", "127.0.0.1:6379") //传递协议、ip、端口
    if err != nil {
        fmt.Printf("conn redis failed, err:%v\n", err)
        return
    }
    fmt.Printf("connect redis successful!!!\n")
    return
}

func testList(conn redis.Conn) {

    _, err := conn.Do("lpush", "book_list", "this is a test", "ksksksksks") //左边进 第二个参数book_lsit是队列名
    if err != nil {
        fmt.Printf("set failed:%s\n", err)
        return
    }

    //reply, err := conn.Do("get", "abc")
    data, err := redis.String(conn.Do("rpop", "book_list")) //右边出,一次只能出队一个元素
    if err != nil {
        fmt.Printf("get failed, err:%v\n", err)
        return
    }

    fmt.Printf(" value:%s\n", data)
}

func main() {
    conn, err := initRedis()
    if err != nil {
        return
    }
    defer conn.Close() //关闭连接

    testList(conn)
}

 执行结果:

 

栈操作实例:

package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

func initRedis() (conn redis.Conn, err error) { //连接redis函数
    conn, err = redis.Dial("tcp", "127.0.0.1:6379") //传递协议、ip、端口
    if err != nil {
        fmt.Printf("conn redis failed, err:%v\n", err)
        return
    }
    fmt.Printf("connect redis successful!!!\n")
    return
}

func testList(conn redis.Conn) {

    _, err := conn.Do("lpush", "book_stack", "this is a test", "ksksksksks") //左边进 第二个参数book_lsit是队列名
    if err != nil {
        fmt.Printf("set failed:%s\n", err)
        return
    }

    //reply, err := conn.Do("get", "abc")
    data, err := redis.String(conn.Do("lpop", "book_list")) //左边出,一次只能出队一个元素
    if err != nil {
        fmt.Printf("get failed, err:%v\n", err)
        return
    }

    fmt.Printf(" value:%s\n", data)
}

func main() {
    conn, err := initRedis()
    if err != nil {
        return
    }
    defer conn.Close() //关闭连接

    testList(conn)
}

 执行结果:

2.6 redis连接池

之前实例都是单个连接,拿到1个连接,针对连接进行操作,如果是1个并发的程序,1个连接是不够的,并且会有线程安全的问题,但是我们可以用连接池来解决。

package main

import (
    "fmt"
    "time"

    "github.com/garyburd/redigo/redis"
)

func initRedis() (conn redis.Conn, err error) { //连接redis函数
    conn, err = redis.Dial("tcp", "127.0.0.1:6379") //传递协议、ip、端口
    if err != nil {
        fmt.Printf("conn redis failed, err:%v\n", err)
        return
    }
    fmt.Printf("connect redis successful!!!\n")
    return
}

func newPool(serverAddr string, passwd string) (pool *redis.Pool) { //第一个参数是服务的地址,第二个是连接时的密码(就是redis的密码)
    return &redis.Pool{ //返回1个结构体的连接池对象
        MaxIdle:     16,                //空闲连接数,即使没有连接请求,也会有空闲连接数在连接池中
        MaxActive:   1024,              //活跃连接数,也就是最大连接数
        IdleTimeout: 240 * time.Second, //空闲连接数超时时间,连接数超时了就会被释放掉
        Dial: func() (redis.Conn, error) { //匿名函数类型变量,用来连接redis
            fmt.Printf("create conn\n")
            conn, err := redis.Dial("tcp", serverAddr)
            if err != nil {
                return nil, err
            }

            if len(passwd) > 0 {
                _, err = conn.Do("auth", passwd)
                if err != nil {
                    return nil, err
                }
            }
            return conn, err
        },
        TestOnBorrow: func(c redis.Conn, t time.Time) error { //匿名函数类型变量,作用:如果从连接池获取连接时,会验证一下这个连接是不是可用的。
            fmt.Printf("verify conn\n") //验证连接

            if time.Since(t) < time.Minute { //如果1分钟之内就不验证了,频繁的ping会影响性能
                return nil
            }
            fmt.Printf("ping conn\n")
            _, err := c.Do("ping")
            return err
        },
    }
}

func testRedisPool() {
    pool := newPool("127.0.0.1:6379", "")

    conn := pool.Get() //获取1个连接
    conn.Do("set", "abc", "3838383833834378473874837483748374")

    val, err := redis.String(conn.Do("get", "abc"))
    fmt.Printf("val:%s err:%v\n", val, err)

    //把连接归还到连接池,并不是关闭连接
    conn.Close()

    fmt.Printf("==========================\n")
    conn = pool.Get()
    conn.Do("set", "abc", "3838383833834378473874837483748374")

    val, err = redis.String(conn.Do("get", "abc"))
    fmt.Printf("val:%s err:%v\n", val, err)

    //把连接归还到连接池
    conn.Close()
}

func main() {
    testRedisPool()
}

 执行结果:

解释:

我们可以发现第一次我们get是建立了连接,在使用完之后close(将该连接归还到连接池了),紧接着下面一个请求,get并没有建立新的连接,而是使用了连接池中刚刚归还的连接,并且因为小于我们的设定时间,也没有去ping redis

三、参考网址

https://www.jianshu.com/p/89ca34b84101

https://studygolang.com/articles/6107


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
GO入门——4. 数组、切片与map发布时间:2022-07-10
下一篇:
GoWeb框架gin发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap