golang操作Redis与面向接口编程实现

33 篇文章 0 订阅
1 篇文章 0 订阅

了解golang接口模式

/* 定义接口 */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/* 定义结构体 */
type struct_name struct {
   /* variables */
}

/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
   /* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
   /* 方法实现*/
}

了解Redis4种数据类型的操作


1. String 类型常见操作

  • set(key, value):给数据库中名称为key的string赋予值value
  • get(key):返回数据库中名称为key的string的value
  • getset(key,value):给名称为key的string赋予上一次的value
  • mget(key1, key2,…, key N):返回库中多个string的value
  • setnx(key, value):添加string,名称为key,值为value
  • setex(key, time, value):向库中添加string,设定过期时间time
  • mset(key N, value N):批量设置多个string的值
  • msetnx(key N, value N):如果所有名称为key i的string都不存在
  • incr(key):名称为key的string增1操作
  • incrby(key, integer):名称为key的string增加integer
  • decr(key):名称为key的string减1操作
  • decrby(key, integer):名称为key的string减少integer
  • append(key, value):名称为key的string的值附加value
  • substr(key, start, end):返回名称为key的string的value的子串

2. Hash类型常见操作

  • hset(key, field, value):向名称为key的hash中添加元素field
  • hget(key, field):返回名称为key的hash中field对应的value
  • hmget(key, (fields)):返回名称为key的hash中field i对应的value
  • hmset(key, (fields)):向名称为key的hash中添加元素field
  • hincrby(key, field, integer):将名称为key的hash中field的value增加integer
  • hexists(key, field):名称为key的hash中是否存在键为field的域
  • hdel(key, field):删除名称为key的hash中键为field的域
  • hlen(key):返回名称为key的hash中元素个数
  • hkeys(key):返回名称为key的hash中所有键
  • hvals(key):返回名称为key的hash中所有键对应的value
  • hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value

3. Set类型常见操作

  • sadd(key, member):向名称为key的set中添加元素member
  • srem(key, member) :删除名称为key的set中的元素member
  • spop(key) :随机返回并删除名称为key的set中一个元素
  • smove(srckey, dstkey, member) :移到集合元素
  • scard(key) :返回名称为key的set的基数
  • sismember(key, member) :member是否是名称为key的set的元素
  • sinter(key1, key2,…key N) :求交集
  • sinterstore(dstkey, (keys)) :求交集并将交集保存到dstkey的集合
  • sunion(key1, (keys)) :求并集
  • sunionstore(dstkey, (keys)) :求并集并将并集保存到dstkey的集合
  • sdiff(key1, (keys)) :求差集
  • sdiffstore(dstkey, (keys)) :求差集并将差集保存到dstkey的集合
  • smembers(key) :返回名称为key的set的所有元素
  • srandmember(key) :随机返回名称为key的set的一个元素

4. list类型常见操作

  • rpush(key, value):在名称为key的list尾添加一个值为value的元素
  • lpush(key, value):在名称为key的list头添加一个值为value的 元素
  • llen(key):返回名称为key的list的长度
  • lrange(key, start, end):返回名称为key的list中start至end之间的元素
  • ltrim(key, start, end):截取名称为key的list
  • lindex(key, index):返回名称为key的list中index位置的元素
  • lset(key, index, value):给名称为key的list中index位置的元素赋值
  • lrem(key, count, value):删除count个key的list中值为value的元素
  • lpop(key):返回并删除名称为key的list中的首元素
  • rpop(key):返回并删除名称为key的list中的尾元素
  • blpop(key1, key2,… key N, timeout):lpop命令的block版本。
  • brpop(key1, key2,… key N, timeout):rpop的block版本。
  • rpoplpush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部

依赖Package

golang redis 包
github.com/garyburd/redigo/redis

Redis 连接池

const (
    RedisURL            ="redis://127.0.0.1:6379"
    redisMaxIdle        = 25   //最大空闲连接数
    redisMaxActive      = 100  //最大的激活连接数
    redisIdleTimeoutSec = 240 //最大空闲连接时间
    //RedisPassword       = ""
)


/*
* Redis 连接池
* NewRedisPool 返回redis连接池
* 参数:  redisURL redis服务; Database redisDB;
* 返回: redis 连接
*/
func NewRedisPool(redisURL string, Database int) *redis.Pool {
    return &redis.Pool{
        MaxIdle: redisMaxIdle,
        MaxActive: redisMaxActive,
        IdleTimeout: redisIdleTimeoutSec * time.Second,
        Dial: func() (redis.Conn, error) {
            // redis://127.0.0.1:6379/0
            URLs := strings.Join([]string{redisURL, strconv.Itoa(Database)}, "/")
            fmt.Println(URLs)
            c, err := redis.DialURL(URLs)
            //c, err := redis.Dial("tcp",redisURL,redis.DialDatabase(5))
            if err != nil {
                return nil, fmt.Errorf("redis connection error: %s", err)
            }
            /*//验证redis密码
            if _, authErr := c.Do("AUTH", RedisPassword); authErr != nil {
                return nil, fmt.Errorf("redis auth password error: %s", authErr)
            }
            */
            return c, err
        },
        TestOnBorrow: func(c redis.Conn, t time.Time) error {
            _, err := c.Do("PING")
            if err != nil {
                return fmt.Errorf("ping redis error: %s", err)
            }
            return nil
        },
    }
}

——————————————————————————————————

设计接口

1. 以key为对象添加数据整合一起组成接口

2. 以批量操作整合一起组成接口

3. 以发布订阅整合一起组成接口

代码实现

package main

import (
    "encoding/json"
    _ "errors"
    "fmt"
    "time"
    _ "reflect"
    "strings"
    "strconv"
	"github.com/garyburd/redigo/redis"
)

const (
    RedisURL            ="redis://127.0.0.1:6379"
    redisMaxIdle        = 25   //最大空闲连接数
    redisMaxActive      = 100  //最大的激活连接数
    redisIdleTimeoutSec = 240 //最大空闲连接时间
    //RedisPassword       = ""
)

/*
* Redis 连接池
* NewRedisPool 返回redis连接池
* 参数:  redisURL redis服务; Database redisDB;
* 返回: redis 连接
*/
func NewRedisPool(redisURL string, Database int) *redis.Pool {
    return &redis.Pool{
        MaxIdle: redisMaxIdle,
        MaxActive: redisMaxActive,
        IdleTimeout: redisIdleTimeoutSec * time.Second,
        Dial: func() (redis.Conn, error) {
            // redis://127.0.0.1:6379/0
            URLs := strings.Join([]string{redisURL, strconv.Itoa(Database)}, "/")
            fmt.Println(URLs)
            c, err := redis.DialURL(URLs)
            //c, err := redis.Dial("tcp",redisURL,redis.DialDatabase(5))
            if err != nil {
                return nil, fmt.Errorf("redis connection error: %s", err)
            }
            /*//验证redis密码
            if _, authErr := c.Do("AUTH", RedisPassword); authErr != nil {
                return nil, fmt.Errorf("redis auth password error: %s", authErr)
            }
            */
            return c, err
        },
        TestOnBorrow: func(c redis.Conn, t time.Time) error {
            _, err := c.Do("PING")
            if err != nil {
                return fmt.Errorf("ping redis error: %s", err)
            }
            return nil
        },
    }
}

/*
* 1. 以key为对象进行操作整合一起组成接口
*/
type ManRedisKey interface {
    Strset(value interface{})
    Strget() string
    Strgetset(value interface{}) string
    ExpireKey(extime int)
    CheckKey() bool
    DelKey() error
    StrsetJson(value interface{})
    StrgetJson() interface{}
}

type RKey struct {
    key string
}

/*
* set(key, value):给数据库中名称为key的string赋予值value
*/
func (manrk *RKey) Strset(value interface{}) {
	c := NewRedisPool(RedisURL,1).Get()
	defer c.Close()
    _, err := c.Do("SET", manrk.key, value)
    if err != nil {
        fmt.Println("set error", err.Error())
    }else{
        fmt.Println("set ok.")
    }
}

/*
* set(key, value):给数据库中名称为key的string赋予值value
*/
func (manrk *RKey) StrsetEX(value interface{}, extime int) {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    _, err := c.Do("SET", manrk.key, value, "EX", extime)
    if err != nil {
        fmt.Println("set error", err.Error())
    }else{
        fmt.Println("set ok.")
    }
}

/*
* get(key):返回数据库中名称为key的string的value
*/
func (manrk *RKey) Strget() string {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    res, err := redis.String(c.Do("GET", manrk.key))
    if err != nil {
        fmt.Println("GET error", err.Error())
        return ""
    }else{
        return res
    }
}

/*
* getset(key, value):给名称为key的string赋予上一次的value
*/
func (manrk *RKey) Strgetset(v interface{}) string {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    res, err := redis.String(c.Do("GETSET", manrk.key, v))
    if err != nil {
        fmt.Println("GETSET error", err.Error())
        return ""
    }else{
        fmt.Println("GETSET ok.")
        return res
    }
}

/*
* 给keys 设置时间
*/
func (manrk *RKey) ExpireKey(extime int) {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    _, err := c.Do("EXPIRE", manrk.key, extime)
    if err != nil {
        fmt.Println("set error", err.Error())
    }
}

/*
* 判断是否存在
*/
func (manrk *RKey) CheckKey() bool {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    exist, err := redis.Bool(c.Do("EXISTS", manrk.key))
    if err != nil {
        fmt.Println(err)
        return false
    } else {
        return exist
    }
}

/*
* 删除key
*/
func (manrk *RKey) DelKey() error {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    _, err := c.Do("DEL", manrk.key)
    if err != nil {
        fmt.Println(err)
        return err
    }
    return nil
}

/*
* 存入json数据
*/
func (manrk *RKey) StrsetJson(value interface{}) {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    datas, _ := json.Marshal(value)
    _, err := c.Do("SET", manrk.key, datas)
    if err != nil {
        fmt.Println("set error", err.Error())
    }else{
        fmt.Println("set ok.")
    }
}

/*
* 获取json数据
*/
func (manrk *RKey) StrgetJson() interface{}{
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    var getdatas map[string]string
    valueget, err := redis.Bytes(c.Do("GET", manrk.key))
    if err != nil {
        fmt.Println(err)
        return 0
    }
    errshal := json.Unmarshal(valueget, &getdatas)
    if errshal != nil {
        return 0
    }
    return getdatas
}



/*
* 2. 以批量操作数据整合一起组成接口
*/
type ManRedisBatch interface {
    Strmset()
    Strmget() ([]string)
}
type BatchDatas struct {
    datas interface{}
}
/*
* mset(key N, value N):批量设置多个string的值
*/
func (manrb *BatchDatas) Strmset() {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    _, err := c.Do("mset", redis.Args{}.AddFlat(manrb.datas)...)
    if err != nil {
        fmt.Println("mset error", err.Error())
    } else {
        fmt.Println("ok")
    }
}
/*
* mget(key1, key2,…, key N):返回库中多个string的value
*/
func (manrb *BatchDatas) Strmget() ([]string) {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    list := []string {}
    res, err := redis.Values( c.Do("mget", redis.Args{}.AddFlat(manrb.datas)...))
    if err != nil {
        fmt.Println("mset error", err.Error())
        return list
    } else {
        for _, v := range res {
            fmt.Println(string(v.([]byte)))
            list = append(list, string(v.([]byte)))
        }
        return list
    }
}

func test() {
    keys := "test1"
    var test1 ManRedisKey = &RKey{key:keys}
    test1.Strset("aaa1")
    fmt.Println(test1.Strget())
    fmt.Println(test1.Strgetset("aaa2"))
    test1.ExpireKey(100)
    fmt.Println(test1.CheckKey())
    test1.DelKey()

    datas1 := map[string]string{"username": "666", "phonenumber": "888"}
    var test2 ManRedisBatch = &BatchDatas{datas:datas1}
    test2.Strmset()

    var test3 ManRedisBatch = &BatchDatas{datas:[]string{"username","phonenumber"}}
    fmt.Println(test3.Strmget())

    var test4 ManRedisKey = &RKey{key:"test4"}
    test4.StrsetJson(map[string]string{"aa1": "111", "aa2": "222"})
    fmt.Println(test4.StrgetJson())
    fmt.Println(test4.Strget())
}

/*
* 管道 按照队列先进先出的原则进行send,receive操作
*/
func sendr() {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()

    c.Send("SET", "userId", "DF123")
    c.Send("GET", "userId")
    c.Flush()
    c.Receive() // reply from SET
    valueGet, errr := c.Receive() // reply from GET
    fmt.Println(redis.String(valueGet,errr))

}

/*
* 发布/订阅
*/
func Subs() {  //订阅者
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()

    psc := redis.PubSubConn{c}
    psc.Subscribe("channel1") //订阅channel1频道
    for {
        switch v := psc.Receive().(type) {
        case redis.Message:
            fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
        case redis.Subscription:
            fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
        case error:
            fmt.Println(v)
            return
        }
    }
}

func Push(message string)  { //发布者
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()

    _,err1 := c.Do("PUBLISH", "channel1", message)
    if err1 != nil {
            fmt.Println("pub err: ", err1)
            return
        }
}



func main() {
	test()
    sendr()
    //发布/订阅
    go Subs()
    go Push("mange *******...")
}

运行结果

在这里插入图片描述

在这里插入图片描述

Hash操作实现

/*
Hash操作

hset(key, field, value):向名称为key的hash中添加元素field
hget(key, field):返回名称为key的hash中field对应的value
hmget(key, (fields)):返回名称为key的hash中field i对应的value
hmset(key, (fields)):向名称为key的hash中添加元素field
hincrby(key, field, integer):将名称为key的hash中field的value增加integer
hexists(key, field):名称为key的hash中是否存在键为field的域
hdel(key, field):删除名称为key的hash中键为field的域
hlen(key):返回名称为key的hash中元素个数
hkeys(key):返回名称为key的hash中所有键
hvals(key):返回名称为key的hash中所有键对应的value
hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value

*/


/*
* 设置值数据类型为 Hash
*
*/
func addto_Hash(k string, f string, v string) {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    _, err := c.Do("hset", k, f, v)
    if err != nil {
        fmt.Println("hset error", err.Error())
    }else{
        fmt.Println("hset ok")
    }
}

//查询数据 - Hash
//result,err := redis.Values(c.Do("hgetall","key"))
func getdata_Hash(k, f string) string {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    res, err := redis.String(c.Do("hget", k, f))
    fmt.Println(reflect.TypeOf(res))
    if err != nil {
        fmt.Println("hget failed", err.Error())
        return "-1"
    } else {
        fmt.Printf("hget value :%s\n", res)
        return res
    }
}


//判断key是否存在
//存在返回  1
//不存在返回  0
//异常返回  -1
func judgekey_Hash(k, f string) int {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    res, err := redis.Int((c.Do("hexists", k, f)))
    if err != nil {
        fmt.Println("hexist failed", err.Error())
        return -1
    } else {
        //fmt.Println("exist or not:", res)
        //fmt.Println(reflect.TypeOf(res))
        return res
    }
    
}

//批量添加数据到redis  Hash
func addarr_Hash(k string, f interface{}) {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    _, err := c.Do("hmset", redis.Args{}.Add(k).AddFlat(f)...)
    if err != nil {
        fmt.Println("hmset error", err.Error())
    } else {
        fmt.Println("ok")
    }
}



// 返回名称为key的hash中元素个数
func getlen_datas(k string) int {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    res, err := redis.Int((c.Do("hlen", k)))
    if err != nil {
        fmt.Println("hexist failed", err.Error())
        return -1
    } else {
        //fmt.Println("exist or not:", res)
        //fmt.Println(reflect.TypeOf(res))
        return res
    }
}


//hkeys(key):返回名称为key的hash中所有键
//返回值为数组
func getall_keys(k string) []string {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    res, err := redis.Values((c.Do("hkeys", k)))
    if err != nil {
        fmt.Println("hexist failed", err.Error())
        return []string {}
    } else {
        list := []string {}
        for _, v := range res {
            list = append(list, string(v.([]byte)))
        }
        fmt.Println(list)
        return list
    }
}


//hvals(key):返回名称为key的hash中所有键对应的value
func getall_vals(k string) []string {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    res, err := redis.Values((c.Do("hvals", k)))
    if err != nil {
        fmt.Println("hexist failed", err.Error())
        return []string {}
    } else {
        list := []string {}
        for _, v := range res {
            list = append(list, string(v.([]byte)))
        }
        fmt.Println(list)
        return list
    }
}



//hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value
//返回 map
func getall_datas(k string) map[string]string {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    res, err := redis.StringMap((c.Do("hgetall", k)))
    if err != nil {
        fmt.Println("hexist failed", err.Error())
        return make(map[string]string)
    } else {
        //转为json
        result, err := json.Marshal(res)
        if err != nil {
            fmt.Println("result is null")
        }
        fmt.Println("result = ", string(result))
        return res
    }
}



//hdel(key, field):删除名称为key的hash中键为field的域
func del_datas(k, f string) {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    _, err := c.Do("HDEL", k, f)
    if err != nil {
        fmt.Println("hdel failed", err.Error())
    } else {
        fmt.Println("hdel ok")
    }
}



//hincrby(key, field, integer):将名称为key的hash中field的value增加integer
func hincrby_test() {
    c := NewRedisPool(RedisURL,1).Get()
    defer c.Close()
    _, err := c.Do("hincrby", "a", "dd", 1)
    if err != nil {
        fmt.Println("hmset error", err.Error())
    } else {
        fmt.Println("ok")
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Golang 是一门支持面向接口编程的语言,这意味着在 Golang 中,我们可以通过定义接口实现多态性。具体来说,我们可以定义一个接口类型,然后让多个不同的类型实现接口,从而使它们可以被视为同一类型,从而实现多态性。 在 Golang 中,接口是一组方法的集合,这些方法定义了该接口所代表的对象应该具有的行为。任何类型只要实现了该接口中定义的所有方法,就可以被视为该接口类型的实例。 下面是一个简单的例子,展示了如何定义一个接口实现接口: ```go package main import "fmt" // 定义一个接口 type Animal interface { Speak() string } // 定义一个结构体类型 type Dog struct { Name string } // 实现 Animal 接口中的 Speak 方法 func (d Dog) Speak() string { return "Woof!" } func main() { // 创建一个 Dog 类型的实例 d := Dog{Name: "Fido"} // 将该实例赋值给 Animal 类型的变量 var a Animal = d // 调用 Animal 接口中的 Speak 方法 fmt.Println(a.Speak()) // 输出: Woof! } ``` 在上面的例子中,我们定义了一个 Animal 接口,它只有一个方法:Speak。然后我们定义了一个 Dog 结构体类型,并实现了 Animal 接口中的 Speak 方法。最后,我们创建了一个 Dog 类型的实例,并将其赋值给 Animal 类型的变量。由于 Dog 类型实现了 Animal 接口中的所有方法,所以它可以被视为 Animal 类型的实例,从而实现了多态性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值