欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > zdpgo_redis_v2 Go语言连接Redis的另一个版本,支持上下文操作,封装了一些便捷的处理操作

zdpgo_redis_v2 Go语言连接Redis的另一个版本,支持上下文操作,封装了一些便捷的处理操作

2026/4/18 13:33:58 来源:https://blog.csdn.net/qq_37703224/article/details/141086466  浏览:    关键词:zdpgo_redis_v2 Go语言连接Redis的另一个版本,支持上下文操作,封装了一些便捷的处理操作

zdpgo_redis_v2

Go语言连接Redis的另一个版本,支持上下文操作,封装了一些便捷的处理操作

安装

github.com/zhangdapeng520/zdpgo_redis_v2

使用教程

快速入门

package mainimport ("context""fmt"redis "github.com/zhangdapeng520/zdpgo_redis_v2"
)var ctx = context.Background()func main() {rdb := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "", // no password setDB:       0,  // use default DB})err := rdb.Set(ctx, "key", "value", 0).Err()if err != nil {panic(err)}val, err := rdb.Get(ctx, "key").Result()if err != nil {panic(err)}fmt.Println("key", val)val2, err := rdb.Get(ctx, "key2").Result()if err == redis.Nil {fmt.Println("key2 does not exist")} else if err != nil {panic(err)} else {fmt.Println("key2", val2)}// Output: key value// key2 does not exist
}

通过URL地址连接Redis

package mainimport ("context""fmt"redis "github.com/zhangdapeng520/zdpgo_redis_v2"
)var ctx = context.Background()func main() {//url := "redis://user:password@localhost:6379/0?protocol=3"url := "redis://:@localhost:6379/0?protocol=3"opts, err := redis.ParseURL(url)if err != nil {panic(err)}rdb := redis.NewClient(opts)err = rdb.Set(ctx, "key", "value", 0).Err()if err != nil {panic(err)}val, err := rdb.Get(ctx, "key").Result()if err != nil {panic(err)}fmt.Println("key", val)val2, err := rdb.Get(ctx, "key2").Result()if err == redis.Nil {fmt.Println("key2 does not exist")} else if err != nil {panic(err)} else {fmt.Println("key2", val2)}// Output: key value// key2 does not exist
}

删除key

package mainimport ("context""fmt""sync""time"redis "github.com/zhangdapeng520/zdpgo_redis_v2"
)func main() {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: ":6379",})_ = rdb.Set(ctx, "key_with_ttl", "bar", time.Minute).Err()_ = rdb.Set(ctx, "key_without_ttl_1", "", 0).Err()_ = rdb.Set(ctx, "key_without_ttl_2", "", 0).Err()checker := NewKeyChecker(rdb, 100)start := time.Now()checker.Start(ctx)iter := rdb.Scan(ctx, 0, "", 0).Iterator()for iter.Next(ctx) {checker.Add(iter.Val())}if err := iter.Err(); err != nil {panic(err)}deleted := checker.Stop()fmt.Println("deleted", deleted, "keys", "in", time.Since(start))
}type KeyChecker struct {rdb       *redis.ClientbatchSize intch        chan stringdelCh     chan stringwg        sync.WaitGroupdeleted   int
}func NewKeyChecker(rdb *redis.Client, batchSize int) *KeyChecker {return &KeyChecker{rdb:       rdb,batchSize: batchSize,ch:        make(chan string, batchSize),delCh:     make(chan string, batchSize),}
}func (c *KeyChecker) Add(key string) {c.ch <- key
}func (c *KeyChecker) Start(ctx context.Context) {c.wg.Add(1)go func() {defer c.wg.Done()if err := c.del(ctx); err != nil {panic(err)}}()c.wg.Add(1)go func() {defer c.wg.Done()defer close(c.delCh)keys := make([]string, 0, c.batchSize)for key := range c.ch {keys = append(keys, key)if len(keys) < cap(keys) {continue}if err := c.checkKeys(ctx, keys); err != nil {fmt.Println("checkKeys failed", err)}keys = keys[:0]}if len(keys) > 0 {if err := c.checkKeys(ctx, keys); err != nil {fmt.Println("checkKeys failed", err)}keys = nil}}()
}func (c *KeyChecker) Stop() int {close(c.ch)c.wg.Wait()return c.deleted
}func (c *KeyChecker) checkKeys(ctx context.Context, keys []string) error {cmds, err := c.rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {for _, key := range keys {pipe.TTL(ctx, key)}return nil})if err != nil {return err}for i, cmd := range cmds {d, err := cmd.(*redis.DurationCmd).Result()if err != nil {return err}if d == -1 {c.delCh <- keys[i]}}return nil
}func (c *KeyChecker) del(ctx context.Context) error {pipe := c.rdb.Pipeline()for key := range c.delCh {fmt.Printf("deleting %s...\n", key)pipe.Del(ctx, key)c.deleted++if pipe.Len() < c.batchSize {continue}if _, err := pipe.Exec(ctx); err != nil {return err}}if _, err := pipe.Exec(ctx); err != nil {return err}return nil
}

hll

package mainimport ("context""fmt"redis "github.com/zhangdapeng520/zdpgo_redis_v2"
)func main() {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: ":6379",})_ = rdb.FlushDB(ctx).Err()for i := 0; i < 10; i++ {if err := rdb.PFAdd(ctx, "myset", fmt.Sprint(i)).Err(); err != nil {panic(err)}}card, err := rdb.PFCount(ctx, "myset").Result()if err != nil {panic(err)}fmt.Println("set cardinality", card)
}

执行LUA脚本

package mainimport ("context""fmt"redis "github.com/zhangdapeng520/zdpgo_redis_v2"
)func main() {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: ":6379",})_ = rdb.FlushDB(ctx).Err()fmt.Printf("# INCR BY\n")for _, change := range []int{+1, +5, 0} {num, err := incrBy.Run(ctx, rdb, []string{"my_counter"}, change).Int()if err != nil {panic(err)}fmt.Printf("incr by %d: %d\n", change, num)}fmt.Printf("\n# SUM\n")sum, err := sum.Run(ctx, rdb, []string{"my_sum"}, 1, 2, 3).Int()if err != nil {panic(err)}fmt.Printf("sum is: %d\n", sum)
}var incrBy = redis.NewScript(`
local key = KEYS[1]
local change = ARGV[1]local value = redis.call("GET", key)
if not value thenvalue = 0
endvalue = value + change
redis.call("SET", key, value)return value
`)var sum = redis.NewScript(`
local key = KEYS[1]local sum = redis.call("GET", key)
if not sum thensum = 0
endlocal num_arg = #ARGV
for i = 1, num_arg dosum = sum + ARGV[i]
endredis.call("SET", key, sum)return sum
`)

将结果转换为结构体

package mainimport ("context"redis "github.com/zhangdapeng520/zdpgo_redis_v2""github.com/zhangdapeng520/zdpgo_redis_v2/spew"
)type Model struct {Str1    string   `redis:"str1"`Str2    string   `redis:"str2"`Bytes   []byte   `redis:"bytes"`Int     int      `redis:"int"`Bool    bool     `redis:"bool"`Ignored struct{} `redis:"-"`
}func main() {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: ":6379",})_ = rdb.FlushDB(ctx).Err()// Set some fields.if _, err := rdb.Pipelined(ctx, func(rdb redis.Pipeliner) error {rdb.HSet(ctx, "key", "str1", "hello")rdb.HSet(ctx, "key", "str2", "world")rdb.HSet(ctx, "key", "int", 123)rdb.HSet(ctx, "key", "bool", 1)rdb.HSet(ctx, "key", "bytes", []byte("this is bytes !"))return nil}); err != nil {panic(err)}var model1, model2 Model// Scan all fields into the model.if err := rdb.HGetAll(ctx, "key").Scan(&model1); err != nil {panic(err)}// Or scan a subset of the fields.if err := rdb.HMGet(ctx, "key", "str1", "int").Scan(&model2); err != nil {panic(err)}spew.Dump(model1)// Output:// (main.Model) {// 	Str1: (string) (len=5) "hello",// 	Str2: (string) (len=5) "world",// 	Bytes: ([]uint8) (len=15 cap=16) {// 	 00000000  74 68 69 73 20 69 73 20  62 79 74 65 73 20 21     |this is bytes !|// 	},// 	Int: (int) 123,// 	Bool: (bool) true,// 	Ignored: (struct {}) {// 	}// }spew.Dump(model2)// Output:// (main.Model) {// 	Str1: (string) (len=5) "hello",// 	Str2: (string) "",// 	Bytes: ([]uint8) <nil>,// 	Int: (int) 123,// 	Bool: (bool) false,// 	Ignored: (struct {}) {// 	}// }
}

版本历史

v0.1.0

  • 初始代码

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com