当前位置: 首页 > news >正文

Go go-redis应用

go-redis 是 Go 语言的一个流行的 Redis 客户端库,它提供了丰富的功能来与 Redis 数据库进行交互。 

1、简单应用 

package mainimport ("context""fmt""log""github.com/redis/go-redis/v9"
)func main() {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "", // no password setDB:       0,  // use default DB})// 设置值err1 := rdb.Set(ctx, "your_key1", "your_value1", 0).Err()if err1 != nil {log.Fatalf("无法设置键值: %v", err1)}// 获取值val, _ := rdb.Get(ctx, "your_key1").Result()fmt.Println("your_key1: ", val)err2 := rdb.LPush(ctx, "your_key2", 111, 222, 333, "444").Err()if err2 != nil {log.Fatalf("无法推送到列表: %v", err2)}// 循环处理邮件队列for {// 从 Redis 队列中获取邮件email, err := rdb.RPop(ctx, "your_key2").Result()if err == redis.Nil {// 队列为空,退出循环fmt.Println("电子邮件队列为空。")break} else if err != nil {log.Fatalf("无法从队列中获取电子邮件: %v", err)} else {fmt.Println(email)}}
}

2、连接池管理

使用 go-redis 可以方便地管理 Redis 连接池,确保高效的连接复用。 

package mainimport ("context""fmt""github.com/redis/go-redis/v9"
)func main() {var ctx = context.Background()// 创建一个新的 Redis 客户端client := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "",DB:       0,PoolSize: 10, // 设置连接池大小})// 使用客户端pong, err := client.Ping(ctx).Result()if err != nil {panic(err)}fmt.Println(pong) // 输出 PONG
}

3、管道和事务

go-redis 支持管道(pipelines)和事务(transactions),可以批量执行命令,减少网络往返次数。 

事务(Transactions)

事务在 Redis 中用来执行一系列命令,这些命令被打包在一起,然后一起执行。如果在执行过程中遇到错误,整个事务将被取消。事务可以保证操作的原子性。

package mainimport ("context""fmt""github.com/redis/go-redis/v9"
)func main() {var ctx = context.Background()// 创建 Redis 客户端client := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "",DB:       0,})// 检查连接pong, err := client.Ping(ctx).Result()if err != nil {fmt.Printf("连接失败: %v", err)return}fmt.Printf("连接成功: %s\n", pong)key1 := "key1"key2 := "key2"// 使用 WATCH 命令监视键err = client.Watch(ctx, func(tx *redis.Tx) error {// 事务中的命令// SetNX函数:当该键不存在时才设置。如果键已经存在,命令将不执行任何操作。第三个参数为设置过期时间,0表示永不过期k1, err := tx.SetNX(ctx, key1, "value1", 0).Result() // 仅当 key1 不存在时设置值if err != nil {return err}if k1 {fmt.Println("key1 设置成功")} else {fmt.Println("key1 已存在,未进行设置操作")}k2, err := tx.SetNX(ctx, key2, "value2", 0).Result() // 仅当 key2 不存在时设置值if err != nil {return err}if k2 {fmt.Println("key2 设置成功")} else {fmt.Println("key2 已存在,未进行设置操作")}// 使用 MULTI 命令开始事务pipe := tx.Pipeline()// 将命令添加到事务队列_, err = pipe.Set(ctx, key1, "value1", 0).Result()if err != nil {return err}_, err = pipe.Set(ctx, key2, "value2", 0).Result()if err != nil {return err}// 使用 EXEC 命令执行事务_, err = pipe.Exec(ctx)if err != nil {return err}return nil}, key1, key2)if err != nil {if err == redis.TxFailedErr {fmt.Println("事务失败,可能因为键被其他客户端修改")} else {fmt.Printf("发生错误: %v", err)}return}// 如果事务成功,获取 key1 和 key2 的值val1, err := client.Get(ctx, key1).Result()if err != nil {fmt.Printf("获取 key1 失败: %v", err)return}val2, err := client.Get(ctx, key2).Result()if err != nil {fmt.Printf("获取 key2 失败: %v", err)return}fmt.Printf("key1: %s, key2: %s\n", val1, val2)
}

使用 Watch 方法监视了两个键 "key1""key2"。在 Watch 的回调函数中,我们尝试设置这两个键的值,如果设置成功,我们使用 Pipeline 方法将设置操作添加到事务队列中。最后,我们使用 Exec 方法提交事务。

请注意,如果 "key1""key2" 在我们设置它们之前已经被其他客户端设置,那么事务将不会执行,并且 Watch 方法将返回 redis.TxFailedErr 错误。在实际应用中,你可能需要根据这个错误来决定是否重试事务。

 事务&管道

package mainimport ("context""fmt""github.com/redis/go-redis/v9"
)func main() {var ctx = context.Background()// 创建一个新的 Redis 客户端client := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "",DB:       0,PoolSize: 10, // 设置连接池大小})// 假设我们想检查并更新的key以及期望的旧值和新值key := "mykey"oldValue := "expectedOldValue"newValue := "newValue"// 事务:使用 MULTI 和 EXEC 命令保证操作的原子性err := client.Watch(ctx, func(tx *redis.Tx) error {// 在事务中获取key的值val, err := tx.Get(ctx, key).Result()if err != nil && err != redis.Nil {return err}// 检查值是否与预期相符if val == oldValue {// 如果相符,尝试更新值_, err := tx.Set(ctx, key, newValue, 0).Result()if err != nil {return err}fmt.Println("更新成功")return nil} else {fmt.Println("键存在,值与预期值不匹配。")return nil // 这里返回nil表示不执行任何操作,事务会因为没有EXEC调用而自动取消}}, key)if err != nil {panic(err)}// 管道:批量发送命令cmds, err := client.Pipelined(ctx, func(pipe redis.Pipeliner) error {pipe.Set(ctx, "key1", "value1", 0)pipe.Get(ctx, "key1")return nil})if err != nil {panic(err)}fmt.Println(cmds) // 输出 [SetResult(string) <nil>, StringResult(value1, nil)]
}

4、发布/订阅模式

发布:

package mainimport ("context""fmt""github.com/redis/go-redis/v9""time"
)func main() {client := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "",DB:       0,})ctx := context.Background()// 发送消息的循环for {err := client.Publish(ctx, "my_channel", "Hello, Redis!").Err()if err != nil {fmt.Printf("发布消息失败: %v\n", err)return}fmt.Println("消息发布成功")// 每5秒发布一条消息time.Sleep(5 * time.Second)}
}

 订阅:

package mainimport ("context""fmt""github.com/redis/go-redis/v9""log""os""os/signal"
)func main() {// 创建 Redis 客户端client := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "",DB:       0,})ctx := context.Background()// 订阅频道pubsub := client.Subscribe(ctx, "my_channel")// 处理接收到的消息go func() {defer func() {if err := pubsub.Close(); err != nil {log.Printf("关闭订阅失败: %v", err)}}()for {msg, err := pubsub.ReceiveMessage(ctx)if err != nil {log.Printf("接收消息失败: %v", err)return}fmt.Printf("接收到消息: %s\n", msg.Payload)}}()// 等待中断信号以退出sigChan := make(chan os.Signal, 1)signal.Notify(sigChan, os.Interrupt)<-sigChanfmt.Println("正在关闭订阅...")
}
package mainimport ("context""github.com/redis/go-redis/v9""log""os""os/signal""syscall""time"
)var ctx = context.Background()func main() {// 创建 Redis 客户端client := redis.NewClient(&redis.Options{Addr:     "localhost:6379",Password: "",DB:       0,})if err := client.Ping(ctx).Err(); err != nil {log.Fatalf("无法连接到 Redis: %v", err)}// 启动订阅者go runSubscriber(client)// 发布者循环发送消息runPublisher(client)// 等待中断信号以优雅退出quit := make(chan os.Signal, 1)signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)<-quitlog.Println("接收到退出信号,正在关闭...")if err := client.Close(); err != nil {log.Fatalf("关闭 Redis 客户端失败: %v", err)}
}func runSubscriber(client *redis.Client) {pubsub := client.Subscribe(ctx, "my_channel")defer func() {if err := pubsub.Close(); err != nil {log.Printf("关闭订阅失败: %v", err)}}()log.Println("订阅者启动,正在监听消息...")for {msg, err := pubsub.ReceiveMessage(ctx)if err != nil {log.Printf("接收消息失败: %v", err)return}log.Printf("接收到消息: %s\n", msg.Payload)}
}func runPublisher(client *redis.Client) {ticker := time.NewTicker(5 * time.Second)defer ticker.Stop()log.Println("发布者启动,将定时发送消息...")for {select {case <-ticker.C:err := client.Publish(ctx, "my_channel", "Hello, Redis!").Err()if err != nil {log.Printf("发布消息失败: %v", err)return}log.Println("消息发布成功")}}
}

 

相关文章:

Go go-redis应用

go-redis 是 Go 语言的一个流行的 Redis 客户端库&#xff0c;它提供了丰富的功能来与 Redis 数据库进行交互。 1、简单应用 package mainimport ("context""fmt""log""github.com/redis/go-redis/v9" )func main() {ctx : context…...

从混乱到有序:PDM系统如何优化物料编码

在现代制造业中&#xff0c;物料管理是企业运营的核心。物料编码作为物料管理的基础&#xff0c;对于确保物料的准确性、唯一性和高效性至关重要。随着产品种类的不断增加和产品变型的多样化&#xff0c;传统的物料编码管理方式已经不能满足企业的需求。本文将探讨产品数据管理…...

npm发布自己的插件包

要发布自己的插件包到npm&#xff0c;可以按照以下步骤进行操作: 1.创建一个新项目 首先确保你已经安装了Node.js和npm。然后&#xff0c;在你的项目目录中初始化一个新的npm项目&#xff1a;npm init命令会引导你创建一个package.json文件&#xff0c;其中包含你插件包的基本…...

Pygame:新手指南与入门教程

在游戏开发领域,pygame 是一个广受欢迎的 Python 库,它提供了开发二维游戏的丰富工具和方法。这个库让开发者可以较少地关注底层图形处理细节,更多地专注于游戏逻辑和玩法的实现。本文将详细介绍 pygame,包括其安装过程、基本概念、主要功能和一个简单游戏的开发流程。 一…...

动态IP与静态IP的优缺点

在网络连接中&#xff0c;使用动态和静态 IP 地址取决于连接的性质和要求。静态 IP 地址通常更适合企业相关服务&#xff0c;而动态 IP 地址更适合家庭网络。让我们来看看动态 IP 与静态 IP 的优缺点。 1.静态IP的优点&#xff1a; 更好的 DNS 支持&#xff1a;静态 IP 地址在…...

上海市计算机学会竞赛平台2024年1月月赛丙组最大的和

题目描述 给定两个序列 &#x1d44e;1,&#x1d44e;2,…,&#x1d44e;&#x1d45b;a1​,a2​,…,an​ 与 &#x1d44f;1,&#x1d44f;2,…,&#x1d44f;&#x1d45b;b1​,b2​,…,bn​&#xff0c;请从这两个序列中分别各找一个数&#xff0c;要求这两个数的差不超过给…...

C++三大特性之继承,详细介绍

阿尼亚全程陪伴大家学习~ 前言 每个程序员在开发新系统时&#xff0c;都希望能够利用已有的软件资源&#xff0c;以缩短开发周期&#xff0c;提高开发效率。 为了提高软件的可重用性(reusability)&#xff0c;C提供了类的继承机制。 1.继承的概念 继承&#xff1a; 指在现有…...

Python推导式详解

引言 推导式&#xff08;Comprehensions&#xff09;是Python中一种简洁且强大的语法结构&#xff0c;可以用来生成列表、字典和集合。推导式使得代码更加简洁、易读&#xff0c;同时也更具Pythonic风格。今天我将将详细介绍列表推导式、字典推导式和集合推导式&#xf…...

stm32中如何实现EXTI线 0 ~ 15与对应IO口的配置呢?

STM32的EXTI控制器支持19 个外部中断/ 事件请求。每个中断设有状态位&#xff0c;每个中断/ 事件都有独立的触发和屏蔽设置。 STM32的19个外部中断对应着19路中断线&#xff0c;分别是EXTI_Line0-EXTI_Line18&#xff1a; 线0~15&#xff1a;对应外部 IO口的输入中断。 线16&…...

Python 短文本匹配,短文本语义相似度,基于大模型的短文本匹配,基于LLMs的短文本语义相似度识别,短文本语义扩充和匹配

1.任务描述 之前在做疾病相似度匹配的时候&#xff0c;堪称史诗级难题&#xff0c;虽然最后加上规则以及一些nlp模型&#xff0c;取得了差强人意的效果&#xff0c;但是短文本的语义相似度匹配一直属于比较难以攻克的难题 2.思路 随着近年大模型的飞速发展&#xff0c;就之前…...

提升接口性能方式汇总

1&#xff0c;sql 2&#xff0c;缓存&#xff0c;尤其面向用户&#xff0c;如app数据。可用redis咖啡&#xff0c;二级缓存。 充分利用redis&#xff0c;redis数据类型很多&#xff0c;平时场景中结合实际情况&#xff0c;找一下对应的redis实现方案 比如Zset可以排序&#…...

C++中的常见语法糖汇总

C中的语法糖是指使代码更简洁、可读性更高的语言特性和简化的语法。以下是一些常见的C语法糖&#xff1a; 1. 自动类型推导&#xff08;auto&#xff09; 使用 auto 关键字可以让编译器自动推导变量的类型&#xff0c;简化变量的声明。 auto x 10; // 编译器推导 x…...

TensorFlow Playground神经网络演示工具使用方法详解

在现代机器学习领域,神经网络无疑是一个重要的研究方向。然而,对于许多初学者来说,神经网络的概念和实际操作可能显得相当复杂。幸运的是,TensorFlow Playground 提供了一个交互式的在线工具,使得我们可以直观地理解和实验神经网络的基本原理。在这篇博客中,我们将详细介…...

【git】subtree 简单教程

git subtree使用案例 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &#x1f31d;分享学习心得&#xff0c;欢迎指正&am…...

C语言基础:字符串函数使用与剖析

strtok&#xff08;分割字符串&#xff09; char * strtok ( char * str, const char * sep ); sep参数是个字符串&#xff0c;定义了用作分隔符的字符集合 第一个参数指定一个字符串&#xff0c;它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标 记。strtok函数找…...

搭建Vulnhub靶机网络问题(获取不到IP)

搭建好靶场后&#xff0c;在攻击机运行arp-scan -l无法发现靶机IP。 这时候去看下靶机网络有没有问题。 重新启动客户机&#xff0c;一直按e进入安全模式&#xff08;要是直接开机了就先按shift进入grub界面&#xff0c;再按e&#xff09;找到ro&#xff0c;将ro改为rw signie…...

Prompt 提示词强大方法论和框架2

自从ChatGPT Chat Generative Pre-trained Transformer于2022年11月30日发布以来&#xff0c;一个新兴的行业突然兴起&#xff0c; 那就是提示工程Prompt engineering&#xff0c;可谓如日冲天。 从简单的文章扩写到RAG&#xff0c;ChatGPT展现了前所未有的惊人能力。 在上一…...

C语言分支和循环(2)

我的相关博客&#xff1a; C语言的分支与循环&#xff08;1&#xff09; 1.switch语句 除了 if 语句外&#xff0c;C语⾔还提供了 switch 语句来实现分⽀结构。 switch 语句是⼀种特殊形式的 的 if...else 结构&#xff0c;⽤于判断条件有多个结果的情况。它把多重 else if…...

14.FreeRTOS 流媒体缓存 Stream Buffer

FreeRTOS 中的 Stream Buffer&#xff08;流媒体缓存&#xff09; 在实时操作系统&#xff08;RTOS&#xff09;中&#xff0c;处理流媒体数据是一项非常关键的任务。FreeRTOS 提供了一种名为 Stream Buffer&#xff08;流媒体缓存&#xff09;的机制&#xff0c;用于高效地管…...

利用ffmpeg把视频分解成图片(每秒x张图)再图片合成视频

1. 视频分解成图片 ffmpeg -i rawVideo.mp4 -r 5 -f image2 img/%04d.png-i rawVideo.mp4 输入文件 -r 5 每秒5帧(1秒5张图) 可不写&#xff0c;默认每秒24帧 -f image2 表示输出的格式图像 可不写&#xff0c;默认图像 img/ 图片放在img文件夹下 %04d.png 图片的命名…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 原创笔记&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 上一篇&#xff1a;《数据结构第4章 数组和广义表》…...

Canal环境搭建并实现和ES数据同步

作者&#xff1a;田超凡 日期&#xff1a;2025年6月7日 Canal安装&#xff0c;启动端口11111、8082&#xff1a; 安装canal-deployer服务端&#xff1a; https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...