前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redis 封装实例

redis 封装实例

原创
作者头像
大发明家
发布2021-12-21 12:33:13
1.6K0
发布2021-12-21 12:33:13
举报
文章被收录于专栏:技术博客文章技术博客文章
代码语言:txt
复制
git clone https://github.com/ccf19881030/redisgoExample.git

当然运行go项目的前提是需要安装golang开发环境

进入到redisgoExample目录,执行如下命令:

代码语言:txt
复制
go mod init ybu.cn/iot

使用go mod init命令初始化一个ybu.cn/iot的自定义包

然后同样是在redisgoExample目录下运行go get命令安装redisgo客户端:

代码语言:txt
复制
go get github.com/gomodule/redigo/redis

此时目录下会多出go.modgo.sum文件,里面包含了redisgo包的引入。

go.mod文件内容如下所示:

代码语言:txt
复制
module ybu.cn/iot
代码语言:txt
复制
go 1.14
代码语言:txt
复制
require github.com/gomodule/redigo v1.8.3

go.sum文件内容如下所示:

代码语言:txt
复制
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
代码语言:txt
复制
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
代码语言:txt
复制
github.com/gomodule/redigo v1.8.3 h1:HR0kYDX2RJZvAup8CsiJwxB4dTCSC0AaUq6S4SiLwUc=
代码语言:txt
复制
github.com/gomodule/redigo v1.8.3/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
代码语言:txt
复制
github.com/gomodule/redigo/redis v0.0.0-do-not-use h1:J7XIp6Kau0WoyT4JtXHT3Ei0gA1KkSc6bc87j9v9WIo=
代码语言:txt
复制
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
代码语言:txt
复制
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
代码语言:txt
复制
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
代码语言:txt
复制
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
代码语言:txt
复制
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
代码语言:txt
复制
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
代码语言:txt
复制
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
代码语言:txt
复制
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

自定义的common包

在redisgoExample目录下新建一个common目录,再创建array.godefine.gointerface.go这三个go文件,用于一些数组、redis配置、redis数据结构的基本操作,

其内容分别如下:

1.array.go

代码语言:txt
复制
package common
代码语言:txt
复制
// ArrayOf does the array contain specified item
代码语言:txt
复制
func ArrayOf(arr []string, dest string) bool {
代码语言:txt
复制
    for i := 0; i < len(arr); i++ {
代码语言:txt
复制
        if arr[i] == dest {
代码语言:txt
复制
            return true
代码语言:txt
复制
        }
代码语言:txt
复制
    }
代码语言:txt
复制
    return false
代码语言:txt
复制
}
代码语言:txt
复制
// ArrayDuplice 数组去重
代码语言:txt
复制
func ArrayDuplice(arr []string) []string {
代码语言:txt
复制
    var out []string
代码语言:txt
复制
    tmp := make(map[string]byte)
代码语言:txt
复制
    for _, v := range arr {
代码语言:txt
复制
        tmplen := len(tmp)
代码语言:txt
复制
        tmp[v] = 0
代码语言:txt
复制
        if len(tmp) != tmplen {
代码语言:txt
复制
            out = append(out, v)
代码语言:txt
复制
        }
代码语言:txt
复制
    }
代码语言:txt
复制
    return out
代码语言:txt
复制
}

2.define.go

代码语言:txt
复制
package common
代码语言:txt
复制
// RedisConnOpt connect redis options
代码语言:txt
复制
type RedisConnOpt struct {
代码语言:txt
复制
    Enable   bool
代码语言:txt
复制
    Host     string
代码语言:txt
复制
    Port     int32
代码语言:txt
复制
    Password string
代码语言:txt
复制
    Index    int32
代码语言:txt
复制
    TTL      int32
代码语言:txt
复制
}

3.interface.go

代码语言:txt
复制
package common
代码语言:txt
复制
// RedisData 存储数据结构
代码语言:txt
复制
type RedisData struct {
代码语言:txt
复制
    Key     string
代码语言:txt
复制
    Field   string
代码语言:txt
复制
    Value   string
代码语言:txt
复制
    Expire  int64
代码语言:txt
复制
}
代码语言:txt
复制
// RedisDataArray RedisData of array
代码语言:txt
复制
type RedisDataArray []*RedisData
代码语言:txt
复制
// IRedis redis client interface
代码语言:txt
复制
type IRedis interface {
代码语言:txt
复制
    // KEYS get patten key array
代码语言:txt
复制
    KEYS(patten string) ([]string, error)
代码语言:txt
复制
    // SCAN get patten key array
代码语言:txt
复制
    SCAN(patten string) ([]string, error)
代码语言:txt
复制
    // DEL delete k-v
代码语言:txt
复制
    DEL(key string) (int, error)
代码语言:txt
复制
    // DELALL delete key array
代码语言:txt
复制
    DELALL(key []string) (int, error)
代码语言:txt
复制
    // GET get k-v
代码语言:txt
复制
    GET(key string) (string, error)
代码语言:txt
复制
    // SET set k-v
代码语言:txt
复制
    //SET(key string, value string) (int64, error)
代码语言:txt
复制
    // SETEX set k-v expire seconds
代码语言:txt
复制
    SETEX(key string, sec int, value string) (int64, error)
代码语言:txt
复制
    // EXPIRE set key expire seconds
代码语言:txt
复制
    EXPIRE(key string, sec int64) (int64, error)
代码语言:txt
复制
    // HGETALL get map of key
代码语言:txt
复制
    HGETALL(key string) (map[string]string, error)
代码语言:txt
复制
    // HGET get value of key-field
代码语言:txt
复制
    HGET(key string, field string) (string, error)
代码语言:txt
复制
    // HSET set value of key-field
代码语言:txt
复制
    //HSET(key string, field string, value string) (int64, error)
代码语言:txt
复制
    // Write 向redis中写入多组数据
代码语言:txt
复制
    Write(data RedisDataArray)
代码语言:txt
复制
}

redisgo的封装

在redisgoExample目录下新建一个cache目录,在此目录下创建一个redis.go的文件,主要用于封装常见的redis命令,其内容如下:

代码语言:txt
复制
package cache
代码语言:txt
复制
import (
代码语言:txt
复制
    "fmt"
代码语言:txt
复制
    "log"
代码语言:txt
复制
    "time"
代码语言:txt
复制
    "github.com/gomodule/redigo/redis"
代码语言:txt
复制
    "ybu.cn/iot/common"
代码语言:txt
复制
)
代码语言:txt
复制
// https://godoc.org/github.com/gomodule/redigo/redis#pkg-examples
代码语言:txt
复制
// https://github.com/gomodule/redigo
代码语言:txt
复制
// RedisClient redis client instance
代码语言:txt
复制
type RedisClient struct {
代码语言:txt
复制
    pool    *redis.Pool
代码语言:txt
复制
    connOpt common.RedisConnOpt
代码语言:txt
复制
    // 数据接收
代码语言:txt
复制
    chanRx chan common.RedisDataArray
代码语言:txt
复制
    // 是否退出
代码语言:txt
复制
    isExit bool
代码语言:txt
复制
}
代码语言:txt
复制
// NewRedis new redis client
代码语言:txt
复制
func NewRedis(opt common.RedisConnOpt) *RedisClient {
代码语言:txt
复制
    return &RedisClient{
代码语言:txt
复制
        connOpt: opt,
代码语言:txt
复制
        pool:    newPool(opt),
代码语言:txt
复制
        chanRx:  make(chan common.RedisDataArray, 100),
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
// newPool 线程池
代码语言:txt
复制
func newPool(opt common.RedisConnOpt) *redis.Pool {
代码语言:txt
复制
    return &redis.Pool{
代码语言:txt
复制
        MaxIdle:     3,
代码语言:txt
复制
        IdleTimeout: 240 * time.Second,
代码语言:txt
复制
        // MaxActive:   10,
代码语言:txt
复制
        // Wait:        true,
代码语言:txt
复制
        Dial: func() (redis.Conn, error) {
代码语言:txt
复制
            c, err := redis.Dial("tcp", fmt.Sprintf("%s:%d", opt.Host, opt.Port))
代码语言:txt
复制
            if err != nil {
代码语言:txt
复制
                log.Fatalf("Redis.Dial: %v", err)
代码语言:txt
复制
                return nil, err
代码语言:txt
复制
            }
代码语言:txt
复制
            if _, err := c.Do("AUTH", opt.Password); err != nil {
代码语言:txt
复制
                c.Close()
代码语言:txt
复制
                log.Fatalf("Redis.AUTH: %v", err)
代码语言:txt
复制
                return nil, err
代码语言:txt
复制
            }
代码语言:txt
复制
            if _, err := c.Do("SELECT", opt.Index); err != nil {
代码语言:txt
复制
                c.Close()
代码语言:txt
复制
                log.Fatalf("Redis.SELECT: %v", err)
代码语言:txt
复制
                return nil, err
代码语言:txt
复制
            }
代码语言:txt
复制
            return c, nil
代码语言:txt
复制
        },
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
// Start 启动接收任务协程
代码语言:txt
复制
func (r *RedisClient) Start() {
代码语言:txt
复制
    r.isExit = false
代码语言:txt
复制
    // 开启协程用于循环接收数据
代码语言:txt
复制
    go r.loopRead()
代码语言:txt
复制
}
代码语言:txt
复制
// Stop 停止接收任务
代码语言:txt
复制
func (r *RedisClient) Stop() {
代码语言:txt
复制
    r.isExit = true
代码语言:txt
复制
    // 关闭数据接收通道
代码语言:txt
复制
    close(r.chanRx)
代码语言:txt
复制
    // 关闭redis线程池
代码语言:txt
复制
    r.pool.Close()
代码语言:txt
复制
}
代码语言:txt
复制
// Write 向redis中写入多组数据
代码语言:txt
复制
func (r *RedisClient) Write(data common.RedisDataArray) {
代码语言:txt
复制
    r.chanRx <- data
代码语言:txt
复制
}
代码语言:txt
复制
// loopRead 循环接收数据
代码语言:txt
复制
func (r *RedisClient) loopRead() {
代码语言:txt
复制
    for !r.isExit {
代码语言:txt
复制
        select {
代码语言:txt
复制
        case rx := <-r.chanRx:
代码语言:txt
复制
            for _, it := range rx {
代码语言:txt
复制
                if len(it.Key) > 0 {
代码语言:txt
复制
                    if len(it.Field) > 0 {
代码语言:txt
复制
                        if _, err := r.HSET(it.Key, it.Field, it.Value); err != nil {
代码语言:txt
复制
                            log.Printf("[%s, %s, %s]: %s\n", it.Key, it.Field, it.Value, err.Error())
代码语言:txt
复制
                        }
代码语言:txt
复制
                    } else {
代码语言:txt
复制
                        if _, err := r.SET(it.Key, it.Value); err != nil {
代码语言:txt
复制
                            log.Printf("[%s, %s, %s]: %s\n", it.Key, it.Field, it.Value, err.Error())
代码语言:txt
复制
                        }
代码语言:txt
复制
                    }
代码语言:txt
复制
                    if it.Expire > 0 {
代码语言:txt
复制
                        r.EXPIRE(it.Key, it.Expire)
代码语言:txt
复制
                    }
代码语言:txt
复制
                }
代码语言:txt
复制
            }
代码语言:txt
复制
        }
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
// Error get redis connect error
代码语言:txt
复制
func (r *RedisClient) Error() error {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    return conn.Err()
代码语言:txt
复制
}
代码语言:txt
复制
// 常用Redis操作命令的封装
代码语言:txt
复制
// http://redis.io/commands
代码语言:txt
复制
// KEYS get patten key array
代码语言:txt
复制
func (r *RedisClient) KEYS(patten string) ([]string, error) {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    return redis.Strings(conn.Do("KEYS", patten))
代码语言:txt
复制
}
代码语言:txt
复制
// SCAN 获取大量key
代码语言:txt
复制
func (r *RedisClient) SCAN(patten string) ([]string, error) {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    var out []string
代码语言:txt
复制
    var cursor uint64 = 0xffffff
代码语言:txt
复制
    isfirst := true
代码语言:txt
复制
    for cursor != 0 {
代码语言:txt
复制
        if isfirst {
代码语言:txt
复制
            cursor = 0
代码语言:txt
复制
            isfirst = false
代码语言:txt
复制
        }
代码语言:txt
复制
        arr, err := conn.Do("SCAN", cursor, "MATCH", patten, "COUNT", 100)
代码语言:txt
复制
        if err != nil {
代码语言:txt
复制
            return out, err
代码语言:txt
复制
        }
代码语言:txt
复制
        switch arr := arr.(type) {
代码语言:txt
复制
        case []interface{}:
代码语言:txt
复制
            cursor, _ = redis.Uint64(arr[0], nil)
代码语言:txt
复制
            it, _ := redis.Strings(arr[1], nil)
代码语言:txt
复制
            out = append(out, it...)
代码语言:txt
复制
        }
代码语言:txt
复制
    }
代码语言:txt
复制
    out = common.ArrayDuplice(out)
代码语言:txt
复制
    return out, nil
代码语言:txt
复制
}
代码语言:txt
复制
// DEL delete k-v
代码语言:txt
复制
func (r *RedisClient) DEL(key string) (int, error) {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    return redis.Int(conn.Do("DEL", key))
代码语言:txt
复制
}
代码语言:txt
复制
// DELALL delete key array
代码语言:txt
复制
func (r *RedisClient) DELALL(key []string) (int, error) {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    arr := make([]interface{}, len(key))
代码语言:txt
复制
    for i, v := range key {
代码语言:txt
复制
        arr[i] = v
代码语言:txt
复制
    }
代码语言:txt
复制
    return redis.Int(conn.Do("DEL", arr...))
代码语言:txt
复制
}
代码语言:txt
复制
// GET get k-v
代码语言:txt
复制
func (r *RedisClient) GET(key string) (string, error) {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    return redis.String(conn.Do("GET", key))
代码语言:txt
复制
}
代码语言:txt
复制
// SET set k-v
代码语言:txt
复制
func (r *RedisClient) SET(key string, value string) (int64, error) {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    return redis.Int64(conn.Do("SET", key, value))
代码语言:txt
复制
}
代码语言:txt
复制
// SETEX set k-v expire seconds
代码语言:txt
复制
func (r *RedisClient) SETEX(key string, sec int, value string) (int64, error) {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    return redis.Int64(conn.Do("SETEX", key, sec, value))
代码语言:txt
复制
}
代码语言:txt
复制
// EXPIRE set key expire seconds
代码语言:txt
复制
func (r *RedisClient) EXPIRE(key string, sec int64) (int64, error) {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    return redis.Int64(conn.Do("EXPIRE", key, sec))
代码语言:txt
复制
}
代码语言:txt
复制
// HGETALL get map of key
代码语言:txt
复制
func (r *RedisClient) HGETALL(key string) (map[string]string, error) {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    return redis.StringMap(conn.Do("HGETALL", key))
代码语言:txt
复制
}
代码语言:txt
复制
// HGET get value of key-field
代码语言:txt
复制
func (r *RedisClient) HGET(key string, field string) (string, error) {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    return redis.String(conn.Do("HGET", key, field))
代码语言:txt
复制
}
代码语言:txt
复制
// HSET set value of key-field
代码语言:txt
复制
func (r *RedisClient) HSET(key string, field string, value string) (int64, error) {
代码语言:txt
复制
    conn := r.pool.Get()
代码语言:txt
复制
    defer conn.Close()
代码语言:txt
复制
    return redis.Int64(conn.Do("HSET", key, field, value))
代码语言:txt
复制
}

测试redis客户端

在redisgoExample目录下新建一个redisgoExample.go文件用于测试,

其内容如下:

代码语言:txt
复制
package main
代码语言:txt
复制
import (
代码语言:txt
复制
    "fmt"
代码语言:txt
复制
    "time"
代码语言:txt
复制
    "ybu.cn/iot/cache"
代码语言:txt
复制
    "ybu.cn/iot/common"
代码语言:txt
复制
)
代码语言:txt
复制
func main() {
代码语言:txt
复制
    fmt.Println("redisgo client demo")
代码语言:txt
复制
    // redis的配置
代码语言:txt
复制
    redisOpt := common.RedisConnOpt{
代码语言:txt
复制
        true,
代码语言:txt
复制
        "127.0.0.1",
代码语言:txt
复制
        6379,
代码语言:txt
复制
        "123456",
代码语言:txt
复制
        3,
代码语言:txt
复制
        240,
代码语言:txt
复制
    }
代码语言:txt
复制
    _redisCli := cache.NewRedis(redisOpt)
代码语言:txt
复制
    // KEYS 示例
代码语言:txt
复制
    keys, err := _redisCli.KEYS("0_last_gb212_2011:*")
代码语言:txt
复制
    if err != nil {
代码语言:txt
复制
        fmt.Println("KEYS failed, err: %v", err)
代码语言:txt
复制
    }
代码语言:txt
复制
    for index, val := range keys {
代码语言:txt
复制
        fmt.Printf("第%d个值为:%s\n", index + 1, val)
代码语言:txt
复制
    }
代码语言:txt
复制
    // GET 示例
代码语言:txt
复制
    key, err := _redisCli.GET("username")
代码语言:txt
复制
    if err != nil {
代码语言:txt
复制
        fmt.Println("GET failed, err: %v", err)
代码语言:txt
复制
    }
代码语言:txt
复制
    fmt.Println("key: ", key)
代码语言:txt
复制
    // SET 示例
代码语言:txt
复制
    //i1, err := _redisCli.SET("month", "12")
代码语言:txt
复制
    //if err != nil {
代码语言:txt
复制
    //  fmt.Println("SET failed, err: %v, %v", err, i1)
代码语言:txt
复制
    //}
代码语言:txt
复制
    // HGET 示例
代码语言:txt
复制
    name, err := _redisCli.HGET("animals", "name")
代码语言:txt
复制
    age, err := _redisCli.HGET("animals", "age")
代码语言:txt
复制
    sex, err := _redisCli.HGET("animals", "sex")
代码语言:txt
复制
    color, err := _redisCli.HGET("animals", "color")
代码语言:txt
复制
    fmt.Printf("animals: [name:%v], [age: %v], [sex: %v], [color: %v]\n", name, age, sex, color)
代码语言:txt
复制
    // HGETALL 示例
代码语言:txt
复制
    animalsMap, err := _redisCli.HGETALL("animals")
代码语言:txt
复制
    for k, v :=  range animalsMap {
代码语言:txt
复制
        fmt.Printf("k : %v, v: %v\t", k, v)
代码语言:txt
复制
    }
代码语言:txt
复制
    // redis client
代码语言:txt
复制
    _redisCli.Start()
代码语言:txt
复制
    defer _redisCli.Stop()
代码语言:txt
复制
    t1 := time.Now().UnixNano() / 1e6
代码语言:txt
复制
    a1, _ := _redisCli.SCAN("GB212_20*")
代码语言:txt
复制
    t2 := time.Now().UnixNano() / 1e6
代码语言:txt
复制
    a2, _ := _redisCli.KEYS("GB212_20*")
代码语言:txt
复制
    t3 := time.Now().UnixNano() / 1e6
代码语言:txt
复制
    fmt.Printf("SCAN time: %d\tlen: %d\nKEYS time: %d\tlen: %d\n", t2-t1, len(a1), t3-t2, len(a2))
代码语言:txt
复制
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 自定义的common包
    • 1.array.go
      • 2.define.go
        • 3.interface.go
        • redisgo的封装
        • 测试redis客户端
        相关产品与服务
        云数据库 Redis
        腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档