代码语言:txt复制
git clone https://github.com/ccf19881030/redisgoExample.git当然运行go项目的前提是需要安装golang开发环境
进入到redisgoExample目录,执行如下命令:
go mod init ybu.cn/iot使用go mod init命令初始化一个ybu.cn/iot的自定义包
然后同样是在redisgoExample目录下运行go get命令安装redisgo客户端:
go get github.com/gomodule/redigo/redis此时目录下会多出go.mod和go.sum文件,里面包含了redisgo包的引入。
go.mod文件内容如下所示:
module ybu.cn/iot代码语言:txt复制go 1.14代码语言:txt复制require github.com/gomodule/redigo v1.8.3go.sum文件内容如下所示:
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.go、define.go、interface.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命令,其内容如下:
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]: %sn", 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]: %sn", 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个值为:%sn", 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: %vt", 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: %dtlen: %dnKEYS time: %dtlen: %dn", t2-t1, len(a1), t3-t2, len(a2))代码语言:txt复制}


