使用 Go 语言与 Redis 构建高效缓存与消息队列系统
什么是 Redis?
- Redis 是一个开源的内存数据库,支持多种数据结构,包括字符串、列表、集合、哈希和有序集合。由于 Redis 运行在内存中,读写速度极快,常被用于构建缓存系统、实时排行榜、会话存储和消息队列等高并发场景下的服务。
- 在这篇博客中,我们将介绍如何使用 Go 语言集成 Redis,构建高效的缓存和消息队列系统。
安装 Redis
- 安装 Redis: 你可以通过以下命令安装 Redis(适用于 Linux 和 macOS):
sudo apt-get install redis-server
- 或者通过 Homebrew 安装:
brew install redis
启动 Redis 服务
redis-server
验证安装
- 可以通过以下命令进入 Redis CLI,验证 Redis 是否正常运行
redis-cli
安装 Go Redis 客户端
- 在 Go 项目中,我们将使用 go-redis/redis 这个流行的 Redis 客户端库。你可以通过以下命令安装:
go get github.com/go-redis/redis/v8
连接 redis
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,
})
string 类型
- set 设置 string 的值
func TestSetKey(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})err := rdb.Set(ctx, "name", "hello world", time.Second*1000).Err()if err != nil {panic(err)}fmt.Println("设置值成功")
}
- get 获取 string 的值
func TestGetKey(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})result, err := rdb.Get(ctx, "name").Result()if err != nil {panic(err)}fmt.Println("result", result)
}
- getset 获取到的值是上一次的值
func TestGetSet(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})result, err := rdb.GetSet(ctx, "name", "hello world").Result()if err != nil {panic(err)}fmt.Println(result)
}
- setnx 如果值存在则不设置,如果不存在则设置
func TestSetNx(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})err := rdb.SetNX(ctx, "name", "hello set nex", time.Second*1000).Err()if err != nil {panic(err)}}
- mget 批量获取值
func TestMGet(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})result, err := rdb.MGet(ctx, "name", "k1", "k2").Result()if err != nil {panic(err)}fmt.Println(result)
}
- 批量设置
func TestMSet(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})err := rdb.MSet(ctx, "k1", "value1", "k2", "value2", "k3", "value3").Err()if err != nil {panic(err)}}
- 自增
// 自增
func TestIncrBy(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})result, err := rdb.IncrBy(ctx, "money", 1).Result()if err != nil {panic(err)}fmt.Println(result)
}
- 自减
func TestDecrBy(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})val, err := rdb.DecrBy(ctx, "money", 1).Result()if err != nil {panic(err)}fmt.Println(val)
}
- 删除
func TestDel(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})err := rdb.Del(ctx, "k1").Err()if err != nil {panic(err)}
}
- 设置过期时间
func TestExpire(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})rdb.Expire(ctx, "key2", 1000*time.Second)
}
哈希类型
- HSet 设置哈希值
func TestHSet(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})result, err := rdb.Ping(ctx).Result()if err != nil {panic(err)}t.Log(result)err = rdb.HSet(ctx, "user", "name", "张德志").Err()if err != nil {panic(err)}t.Log("设置hash成功")
}
- HGet 获取哈希值
func TestHGet(t *testing.T) {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err := rdb.Ping(ctx).Result()if err != nil {panic(err)}t.Logf("连接数据库成功")result, err1 := rdb.HGet(ctx, "user", "name").Result()if err1 != nil {panic(err1)}t.Logf("获取值:%s", result)
}
- TestHGetAll 获取所有哈希值
func TestHGetAll(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}t.Log("连接数据库成功")result, err1 := rdb.HGetAll(ctx, "user").Result()if err1 != nil {panic(err1)}t.Log(result)
}
- HIncrBy 哈希累加
func TestHIncrBy(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}t.Log("数据库连接成功")count, err1 := rdb.HIncrBy(ctx, "user", "count", 2).Result()if err1 != nil {panic(err1)}t.Log(count)
}
- HKeys 获取所有 keys
func TestHKeys(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}t.Log("连接数据库成功")keys, err1 := rdb.HKeys(ctx, "user").Result()if err1 != nil {panic(err)}t.Log(keys)
}
- HLen 查询字段数量
func TestHLen(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}t.Log("连接数据库成功")result, err1 := rdb.HLen(ctx, "user").Result()if err1 != nil {panic(err1)}t.Log(result)}
- HMGet 批量获取
func TestMGet(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}result, err1 := rdb.HMGet(ctx, "user", "name", "count").Result()if err1 != nil {panic(err)}t.Log(result)
}
- HMSet 批量设置
func TestHMSet(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}data := make(map[string]interface{})data["name"] = "周华建"data["age"] = 44data["gender"] = "男"err = rdb.HMSet(ctx, "user", data).Err()if err != nil {panic(err)}
}
- HDel 删除值
func TestHDel(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}err = rdb.HDel(ctx, "user", "name").Err()if err != nil {panic(err)}}
- 检测是否存在
func TestHExists(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}result, err1 := rdb.HExists(ctx, "user", "name").Result()if err1 != nil {panic(err1)}t.Log(result)
}
List 类型
- TestLPush 左侧插入
func TestLPush(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}err = rdb.LPush(ctx, "key", 1, 2, 3, 4, 5).Err()if err != nil {panic(err)}t.Log("插入成功")
}
- 判断集合左侧是否可以插入,如果存在则不插入,如果不存在则插入
func TestLPushX(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}err = rdb.LPushX(ctx, "key", 6, 7, 8).Err()if err != nil {panic(err)}
}
- 从右则删除一个值并返回删除后的值
func TestRPop(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}val, err1 := rdb.RPop(ctx, "key").Result()if err1 != nil {panic(err1)}t.Log(val)
}
- RPush 从列表右则插入值
func TestRPush(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}err = rdb.RPush(ctx, "key", 12).Err()if err != nil {panic(err)}
}
- LPop 从左侧删除
func TestLPop(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}result, err1 := rdb.LPop(ctx, "key").Result()if err1 != nil {panic(err1)}fmt.Println(result)
}
- LLen 获取集合的长度
func TestLLen(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}result, err1 := rdb.LLen(ctx, "key").Result()if err1 != nil {panic(err1)}t.Log(result)
}
- 遍历集合
func TestLRange(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}result, err1 := rdb.LRange(ctx, "key", 0, -1).Result()if err1 != nil {panic(err1)}t.Log(result)}
- 删除数据
func TestLRem(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}t.Log("数据库连接成功")err = rdb.LRem(ctx, "key", 0, -1).Err()if err != nil {panic(err)}t.Log("删除成功")}
- 获取值的索引
func TestLIndex(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}val, err := rdb.LIndex(ctx, "key", 1).Result()if err != nil {panic(err)}t.Log(val)
}
set 集合
- sadd 添中集合
func TestSAdd(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}err = rdb.SAdd(ctx, "set", 100).Err()if err != nil {panic(err)}t.Log("添加集合成功")
}
- scard 获取集合元素个数
func TestSCard(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}t.Log("连接数据库成功")size, err := rdb.SCard(ctx, "set").Result()if err != nil {panic(err)}t.Log(size)
}
3.sIsmember 判断元素是否在集合中
func TestSIsMember(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}ok, _ := rdb.SIsMember(ctx, "key", 100).Result()if !ok {t.Log("集合不含令指定元素")return}t.Log("集合包含指定元素")
}
- smembers 获取集合中所有的元素
func TestSMembers(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}values, err1 := rdb.SMembers(ctx, "set").Result()if err1 != nil {panic(err1)}t.Log(values)
}
- srem 删除集合中元素
func TestSRem(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}err = rdb.SRem(ctx, "set", 100).Err()if err != nil {panic(err)}t.Log("删除成功")
}
- SPop 随机删除并返回删除的值
func TestSPop(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}val, _ := rdb.SPop(ctx, "set").Result()t.Log(val)vals, _ := rdb.SPopN(ctx, "set", 5).Result()t.Log(vals)
}
可排序集合
- zadd 添加一个或多个元素到集合,如果元素已经存在则更新分数
func TestZAdd(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}err = rdb.ZAdd(ctx, "zAdd", redis.Z{Score: 2.5, Member: "张德志"}).Err()if err != nil {panic(err)}t.Log("插入成功")
}
- zcard 返回集合元素个数
func TestZCard(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}size, err1 := rdb.ZCard(ctx, "zAdd").Result()if err1 != nil {panic(err)}t.Log(size)}
- zCount 获取某个区间的值
func TestZCount(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}size, err1 := rdb.ZCount(ctx, "zAdd", "1", "5").Result()if err1 != nil {panic(err1)}t.Log(size)}
- ZIncrBy 增加元素的分数
func TestZIncrBy(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}err = rdb.ZIncrBy(ctx, "zAdd", 2, "张德志").Err()if err != nil {panic(err)}
}
- zrange 返回集合中某个索引范围的元素
func TestZRange(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}result, err1 := rdb.ZRange(ctx, "zAdd", 0, -1).Result()if err1 != nil {panic(err1)}t.Log(result)}
- ZRangeByScore 根据分数范围返回集合元素,元素根据分数从小到大排序,支持分页
func TestZRangeByScore(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}opt := redis.ZRangeBy{Min: "2",Max: "1000",Offset: 0,Count: 5,}vals, err1 := rdb.ZRangeByScore(ctx, "set", &opt).Result()if err1 != nil {panic(err1)}t.Log(vals)
}
- 根据指定 key 删除元素
func TestZRem(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}err = rdb.ZRem(ctx, "zAdd", "张德志").Err()if err != nil {panic(err)}t.Log("删除成功")
}
- ZRemRangeByRank 根据索引范围删除元素
func TestZRemRangeByRank(t *testing.T) {var err errorctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})_, err = rdb.Ping(ctx).Result()if err != nil {panic(err)}err = rdb.ZRemRangeByRank(ctx, "zAdd", 0, 1).Err()if err != nil {panic(err)}t.Log("删除成功")
}
相关链接
演示地址
获取更多
源码地址

相关文章:
使用 Go 语言与 Redis 构建高效缓存与消息队列系统
什么是 Redis? Redis 是一个开源的内存数据库,支持多种数据结构,包括字符串、列表、集合、哈希和有序集合。由于 Redis 运行在内存中,读写速度极快,常被用于构建缓存系统、实时排行榜、会话存储和消息队列等高并发场景…...
springboot 整合spring ai实现 基于知识库的客服问答
rag 需求产生的背景介绍: 在使用大模型时,常遇到的问题之一是模型可能产生幻觉,即生成的内容缺乏准确性。此外,由于大模型不直接访问企业的专有数据,其响应可能会显得泛泛而谈,不够精准或具体,…...
云原生(四十九) | WordPress源码部署
文章目录 WordPress源码部署 一、WordPress部署步骤 二、创建项目目录 三、上传源码到WordPress 四、配置安全组 五、配置WordPress 六、访问WordPress WordPress源码部署 一、WordPress部署步骤 第一步:创建项目目录 第二步:上传源码到项目目…...
Spring Boot 集成 LiteFlow 实现业务流程编排
LiteFlow 是一款轻量级的流程编排框架,它允许开发者通过简单的配置方式,将复杂的业务流程分解为多个独立的节点,然后通过定义规则来编排节点,达到解耦业务逻辑、提高代码可维护性的目的 1. LiteFlow 的基本概念 在 LiteFlow 中,主要有以下几个概念: 节点 (Node):代表一…...
在 Android Studio 中引入android.os.SystemProperties
在 Android Studio 中引入android.os.SystemProperties 前言 网上有很多种方法,其中直接导入包的办法是行不通的,昨天自己发现问题后也踩了很多坑,现在把问题解决了也全面汇总了几种方法,确保可以百分百引入 1. layoutlib.jar包…...
代码随想录算法训练营总结
这几天一直有事情需要忙,所以现在来准备总结以下训练营的成果。 先说以下总体感受,非常值得!!! 从两个月前开始跟着每天看发布的任务,然后每天坚持打卡,收获还是很大的,从数组开始…...
【uniapp】使用uniapp实现一个输入英文单词翻译组件
目录 1、组件代码 2、组件代码 3、调用页面 4、展示 前言:使用uniapp调用一个在线单词翻译功能 1、组件代码 2、组件代码 YouDaoWordTranslator <template><view class"translator"><input class"ipttext" type"te…...
6. 继承、重写、super、final
文章目录 一、重新定义需求二、继承1. 继续分析2. 概念3. 代码① 父类② 子类③ 测试结果 4. 饿狼传说之多层继承① 概念② 代码 5. 多继承 三、方法的重写1. 情境2. 代码① 吃什么② 怎么叫(Override重写) 3. 小结 四、super1. 啃老2. 啃老啃到底 五、final1. 用途及特征2. 举…...
Redis 其他类型 渐进式遍历
我们之前已经学过了Redis最常用的五个类型了,然而Redis还有一些在特定场景下比较好用的类型 Redis最关键的五个数据类型: 上面的类型是非常常用,很重要的类型。 除此之外的其他类型不常用,只是在特定的场景能够发挥用处&#…...
科研绘图系列:R语言绘制SCI文章图2
文章目录 介绍加载R包导入数据图a图b图d系统信息介绍 文章提供了绘制图a,图b和图d的数据和代码 加载R包 library(ggplot2) library(dplyr) library(readxl) library(ggpmisc)导入数据 数据可从以下链接下载(画图所需要的所有数据): 百度网盘下载链接: https://pan.baid…...
ARM知识点三和串口代码的编写流程
ARM的一些常见问题 ARM 体系结构的主要特点是什么? 精简指令集 (RISC):ARM 采用 RISC 结构,指令集较小且简单,执行效率高。相比于复杂指令集 (CISC),RISC 更强调每条指令的执行速度。低功耗设计:ARM 处理…...
【unity踩坑】打开vs2022没有文字联想/杂项文件
unity打开vs2022没有文字联想 修改外置编辑器安装unity开发插件vs编辑器显示杂项文件 修改外置编辑器安装unity开发插件 参考 在unity项目里选择Edit-> Preferences->External Tools然后更换编辑器 在vs工具界面添加unity游戏开发选项。 重新打开还是有问题ÿ…...
WebGoat JAVA反序列化漏洞源码分析
目录 InsecureDeserializationTask.java 代码分析 反序列化漏洞知识补充 VulnerableTaskHolder类分析 poc 编写 WebGoat 靶场地址:GitHub - WebGoat/WebGoat: WebGoat is a deliberately insecure application 这里就不介绍怎么搭建了,可以参考其他…...
大数据-161 Apache Kylin 构建Cube 按照日期、区域、产品、渠道 与 Cube 优化
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...
uni-app使用v-show编译成微信小程序的问题
问题 在uni-app使用v-show语法编译成微信小程序会有一个问题 当我们设置成v-show"false" 在Hbuilder X里面确实没有显示 然后运行到 微信开发程序里面 发现显示了出来,说明设置的 v-show"false"没有起作用 解决办法 首先去uniapp官网查看v…...
充电宝租赁管理系统网站毕业设计SpringBootSSM框架开发
目录 1. 概述 2. 技术选择与介绍 3. 系统设计 4. 功能实现 5. 需求分析 1. 概述 充电宝租赁管理系统网站是一个既实用又具有挑战性的项目。 随着移动设备的普及和人们日常生活对电力的持续依赖,充电宝租赁服务已成为现代都市生活中的一项重要便利设施。它不仅为…...
喜讯!迈威通信TSN产品通过“时间敏感网络(TSN)产业链名录计划”评测,各项指标名列前茅
TSN技术,作为推动企业网络化与智能化转型的关键力量,已成为工业网络迈向下一代演进的共识方向,正加速重构工业网络的技术架构与产业生态。为响应这一趋势,工业互联网产业联盟携手中国信息通信研究院及50余家产学研用单位ÿ…...
国产工具链GCKontrol-GCAir助力控制律开发快速验证
前言 随着航空领域技术的不断发展,飞机的飞行品质评估和优化成为了航空领域的一个重要任务,为了确保飞行器在各种复杂条件下的稳定性,控制律设计过程中的模型和数据验证需要大量仿真和测试。 本文将探讨基于世冠科技的国产软件工具链GCKont…...
嵌入式开发:STM32 硬件 CRC 使用
测试平台:STM32G474系列 STM32硬件的CRC不占用MCU的资源,计算速度快。由于硬件CRC需要配置一些选项,配置不对就会导致计算结果错误,导致使用上没有软件计算CRC方便。但硬件CRC更快的速度在一些有时间资源要求的场合还是非…...
基于STM32的智能家居语音控制系统:集成LD3320、ESP8266设计流程
一、项目概述 项目目标和用途 近年来,智能家居产品逐渐成为家庭生活中不可或缺的一部分。为了提升家庭生活的便捷性和舒适度,本项目旨在设计一款基于STM32F407VGT6(Cortex-M4内核)微控制器的多功能智能家居语音控制系统。该系统…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
Vue3中的computer和watch
computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...
【Java】Ajax 技术详解
文章目录 1. Filter 过滤器1.1 Filter 概述1.2 Filter 快速入门开发步骤:1.3 Filter 执行流程1.4 Filter 拦截路径配置1.5 过滤器链2. Listener 监听器2.1 Listener 概述2.2 ServletContextListener3. Ajax 技术3.1 Ajax 概述3.2 Ajax 快速入门服务端实现:客户端实现:4. Axi…...
