铁佛 发表于 2022-8-30 03:21:55

[go-redis] go操作redis数据库

先上命令速查网站,菜鸟yyds
https://www.runoob.com/redis/redis-strings.html
操作redis的包是go-redis/redis
官方文档 https://redis.uptrace.dev/guide/
github https://github.com/go-redis/redis
创建项目
创建test文件夹
创建 Redis_test.go 文件
直接上代码,代码解释全写在注释里
package test

import (
        "context"
        "encoding/json"
        "fmt"
        "github.com/go-redis/redis/v8"
        "testing"
        "time"
)


var ctx = context.Background()

var rdb *redis.Client

func init() {
        rdb = redis.NewClient(&redis.Options{
                //        端口需要改,这里是docker的端口
                Addr:          "localhost:49153",
                Password: "redispw", // no password set
                DB:                  0,// use default DB
                PoolSize:15,
                MinIdleConns: 10, //在启动阶段创建指定数量的Idle连接,并长期维持idle状态的连接数不少于指定数量;。
                //超时
                //DialTimeout:5 * time.Second, //连接建立超时时间,默认5秒。
                //ReadTimeout:3 * time.Second, //读超时,默认3秒, -1表示取消读超时
                //WriteTimeout: 3 * time.Second, //写超时,默认等于读超时
                //PoolTimeout:4 * time.Second, //当所有连接都处在繁忙状态时,客户端等待可用连接的最大等待时长,默认为读超时+1秒。
        })
}


//        基础使用
func Test_Base(t *testing.T) {
        //        添加key
        //0表示没有过期时间
        rdb.Set(ctx, "testKey", "xxx", 0)

        //        获取值
        val, err := rdb.Get(ctx, "testKey").Result()
        if err != nil {
                fmt.Println("错误", err)
        }
        fmt.Println("值:", val)

        //        设置key过期时间 成功true
        rdb.Expire(ctx, "testKey", time.Second*60)

        //        存在返回1
        rdb.Exists(ctx, "testKey")

        //        key不存在时设置值
        rdb.SetNX(ctx, "unkey", "val", 0)

        rdb.Set(ctx, "testKey2", "xxx", 0)
        //        删除key 可删除多个
        rdb.Del(ctx, "testKey2", "testKey")

}

//        字符串
func Test_String(t *testing.T) {
        //        设置值
        rdb.Set(ctx, "strKey", 100, 0)
        rdb.Set(ctx, "straey", 100, 0)

        //        key自增1
        rdb.Incr(ctx, "strKey")
        //        增加 66
        rdb.IncrBy(ctx, "straey", 66)

        //        -1
        rdb.Decr(ctx, "straey")
        //        -5
        rdb.DecrBy(ctx, "straey", 5)

        //        过期时间
        rdb.TTL(ctx, "strKey")
        //        str*ey                : *为任意字符串
        //        strey : 匹配[] 内的单个字符 strkey,strKey,straey,strcey
        //        str?ey                : ? 任意单个字符
        //        扫描key
        iter := rdb.Scan(ctx, 0, "str?ey", 0).Iterator()
        for iter.Next(ctx) {
                fmt.Println("keys", iter.Val(), ": val", rdb.Get(ctx, iter.Val()).Val())
        }
        if err := iter.Err(); err != nil {
                panic(err)
        }

}

//        哈希
func Test_Hash(t *testing.T) {
        rdb.HMSet(ctx,"hkey1","name","shushan","age",99,"b",true)

        //        以结构体存入 注意redis tag
        type User struct {
                Name string `json:"name,omitempty" redis:"name"`
                Ageint    `json:"age,omitempty" redis:"age"`
                B    bool   `json:"b,omitempty" redis:"b"`
                //...
        }
        user1 := User{
                Name: "shushan2",
                Age:55,
                B:    true,
        }
        //        结构体序列化反序列化map 你也可以用其他包进行转化为map,但是注意转化后的键名大小写问题
        m := make(mapinterface{})
        buf,_ := json.Marshal(user1)
        _ = json.Unmarshal(buf,&m)

        //        存入
        rdb.HSet(ctx, "user4", m)

        //        取出绑定到结构体 map也行
        var user User
        rdb.HGetAll(ctx,"user4").Scan(&user)
        fmt.Printf(" %#v \n ",user)
        //        test.User{Name:"shushan2", Age:55, B:true}

        //        获取key下的所有值   *匹配方式与string的所有原理一样
        iter := rdb.HScan(ctx,"user4",0,"*",0).Iterator()
        for iter.Next(ctx) {
                fmt.Println("keys", iter.Val())
        }
        if err := iter.Err(); err != nil {
                panic(err)
        }
}


//        列表
func Test_List(t *testing.T) {
        //        添加
        rdb.LPush(ctx,"listKey1",111,222,333,444)
        rdb.RPush(ctx,"listKey1",5555)
        //        不存在不添加
        rdb.LPushX(ctx,"unlistKey",111)

        var intf []int
        //        根据索引获取 绑定到数组
        rdb.LRange(ctx,"listKey1",0,10).ScanSlice(&intf)
        fmt.Println(intf)

        var i int
        //        弹出
        rdb.LPop(ctx,"listKey1").Scan(&i)
        fmt.Println(i)

        //....

}



//        集合
func Test_Set(t *testing.T) {
        //        添加
        rdb.SAdd(ctx,"setKey1","m1","onlyk1")
        rdb.SAdd(ctx,"setKey2","m2","xca")


        sl,_:= rdb.SDiff(ctx,"setKey1","setKey2").Result()
        fmt.Println(sl)
        // onlyk1,m1

        //随机移除
        var val string
        rdb.SPop(ctx,"setKey1").Scan(&val)
        fmt.Println(val)

        // .....
}

//        管道
func Test_Pipe(t *testing.T) {
        //         官方描述
        //         Redis 管道允许客户端命令服务器通过执行任务而通过执行任务来提高您的性能。
        //        在管道中,像命令命令一样将编写 + 使用命令来执行任务,并将其用于执行任务,执行任务不是一个地执行100个命令。
        //        理解为命令就像石头,一次运送一个石头
        //        使用管道等于 用车装石头Exec 时就运送过去
        pipe := rdb.Pipeline()

        incr := pipe.Set(ctx, "pip_test","bt",0)
        pipe.Expire(ctx, "pip_test", time.Hour)

        //        提交
        cmds, err := pipe.Exec(ctx)
        if err != nil {
                fmt.Println(err)
        }
        for _, cmd := range cmds {
                fmt.Println(cmd.String())
        }

        // 该值得Exec提交后有效
        fmt.Println(incr.Val())
}其他操作都可以查看go-redis的源码或者直接打出rdb.命令,go-redis 的函数命名方式和redis的命令是差不多的
The end

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: [go-redis] go操作redis数据库