初识Redis · C++客户端string

目录

前言:

string的API使用

set get:

expire:

NX XX:

mset,mget:

getrange setrange:

incr decr


前言:

在前文,我们已经学习了Redis的定制化客户端怎么来的,以及如何配置好Redis定制化客户端,并且简单学习了一下RESP,其实也就是了解了一下为什么Redis可以定制化客户端而已,那么,我们现在有了Redis定制化客户端的条件,我们自然就可以使用大佬们封装好的Redis的API了。

那么在本文呢,我们涉及到的是string,list和hash的多组API,因为我们是在命令行敲过的,所以学习起来也是非常快的了。

废话不多说,进入主题吧!


string的API使用

对于string的API使用,我们大致分为了 set get expire mset mget getrange setrange incr decr,大致就这么多命令,因为其他命令其实也大差不差,我们就使用过这些也都清楚了。

set get

我们创建好了redis对象之后,啥也不管,直接set,我们可以看到它的参数还是挺多的,但是当我们一看,第一个参数是key,第二个参数是val,第三个参数是chrno的时间,这不就是存活时间吗,第四个参数是一些设置,比如NX,XX等。

这样一看是非常清楚的了。

但是我们发现set的参数是Stringview类型的,这个类型和string类型来说最大的区别就是这个类型是只读的,我们可以通过阅读源码简单了解:

      begin() const noexcept{ return this->_M_str; }constexpr const_iteratorend() const noexcept{ return this->_M_str + this->_M_len; }constexpr const_iteratorcbegin() const noexcept{ return this->_M_str; }constexpr const_iteratorcend() const noexcept{ return this->_M_str + this->_M_len; }

这里是它经过重重封装后的源码,我们可以发现它的迭代器都是const类型,也就是不允许我们修改*this了,它即只读的

因为是只读的,所以针对只读的这个操作做了很多优化,效率就比普通的std::string快了。当然了,在C++17中,标准库也提供了std::string_view,操作和string类似,只是包括了一些只读的方法。

那么我们既然set了,我们肯定要get,我们先看看get的返回值:

通过返回值和备注,我们看到了它的返回值是OptionalString,如果key是不存在的,那么会返回的就是通过nullop构造的OptionalString对象。那么OptionalString是什么呢~

实际上,它的出现是因为为了更好的处理key不存在的这个情况,在我们学习命令行的时候,我们如果使用get查看一个不存在的key,返回值是nil,也就是空的意思,那么如果它的返回值是string,我们如何表达nil

如果返回空串,我们并不排除key对应的value就是空串,如果我们再复杂一点,返回一个string*,指向的是空就代表nil,可是这样又会引发出内存安全的问题。

所以,Redis官方给出的操作是给了一个类型:OptionalString,主要是为了处理nil的情况。

但是作为C++学习者我们不能不知道boost在C++14的时候就已经引入了optional<std::string>的概念了,后来在C++17的时候我们直接就包含optional的头文件就行了。

我们先来看一段正确的使用:

void test_1(Redis& redis)
{redis.flushall();redis.set("key","111");auto value = redis.get("key");if(value)std::cout << value.value() << std::endl;else std::cout << "值不存在" << std::endl;}

我们一共发现了三处左右较为陌生的点,一个是我们使用auto来接收,一个是我们用if来判断value,一个是我们使用的value.value()打印。

首先,我们最能够理解的点是,<<运算符并不支持OptionalString的打印,所以我们需要通过value()方法来返回string类型,其实我们也能通过*value来解决,它们的返回值都是string,*是重载了解引用操作符,.value()就是显示的调用了对应的成员函数。

  if(value)std::cout << *value << std::endl;else std::cout << "值不存在" << std::endl;

其次,我们还能理解的是,如果我们get的是一个不存在的键值,那么OptionalString返回值就是类似于nil的结果,所以我们最好是做一个类型检查。

最后,我们使用auto来接收,其实我们使用optional<string>接收也不是不行,但是为了方便嘛,我们可以直接使用auto接收。不过就需要你包含对应的头文件了。

对应value()方法有一个特点就是如果key不存在,就会抛异常,像这样

从上面这个代码的例子,我们认识了OptionalStringstringView

那么为了测试方便,我们最好在对Redis进行操作的时候flushall一下,以下是第一个测试的代码:

void test_1(Redis &redis)
{redis.flushall();redis.set("key", "111");auto value = redis.get("key");// std::optional<std::string> value = redis.get("key");// if(value)//     std::cout << *value << std::endl;// else//     std::cout << "值不存在" << std::endl;std::cout << value.value() << std::endl;
}
int main()
{Redis redis("tcp://127.0.0.1:6379");test_1(redis);return 0;
}

expire:

然后我们来测试以下超时时间,在set的构造函数中,我们直接加就可以了:

void test_2(Redis &redis)
{redis.flushall();redis.set("key","111",std::chrono::seconds(10));using namespace std::chrono_literals;redis.set("key1","222",10s);std::this_thread::sleep_for(3s);long long time = redis.ttl("key");std::cout << "剩余时间为:" << time << std::endl;}

这里的代码就比较简单了,第一个点是设置过期时间有两种方式,一种是使用命令空间chrono的seconds函数或者millonseconds函数,第二种方式是我们引入命名空间chrono_literals,这样我们就可以直接使用字面值常量了。

然后我们就正常根据ttl的返回值,来接收以下time就可以了:

至于为什么使用chrono等,因为C++不像py可以直接传10表示时间,C++没有内置时间单位,所以需要一个库专门用来表示时间的,就像上面的两个。

NX XX:

接着我们来测试NX和XX:

一般默认的是ALWAYS,XX对应的是EXIST,NX对应的是NOT_EXIST:

void test_3(Redis &redis)
{redis.flushall();redis.set("key", "111", 0s,sw::redis::UpdateType::NOT_EXIST);auto value = redis.get("key");if(value)std::cout << value.value() << std::endl;else   std::cout << "not exist"<< std::endl;
}

mset,mget

对于mset和mget来说就是今天的难点了算是,当然仅仅相对而言,它不过是需要我们引入迭代器的概念而已。

由于传键值对的时候,get和mget的键值对都是pair类型的,所以我们使用mget的时候,官方给我们提供了两个角度,一个是使用initailizer_list,一个是使用容器的迭代器

void test_4(Redis &redis)
{redis.flushall();// redis.mset({"key1","111","key2","222"}); // errorredis.mset({std::make_pair("key","111"),std::make_pair("key1","222")});std::vector<std::pair<std::string, std::string>> vec{std::make_pair("key2","222"),std::make_pair("key3","333")};std::vector<std::pair<std::string, std::string>> vec2{{"key4","444"},{"key5","555"}};redis.mset(vec.begin(), vec.end());redis.mset(vec2.begin(), vec2.end());std::vector<std::string> result;auto iter = std::back_inserter(result); redis.mget({"key","key2","key4"},iter);for(auto ele:result){std::cout << ele << ' ';}std::cout << std::endl;
}

对于mset和mget来说,较为特殊,使用mset的时候,我们有两种方式,一种,我们可以直接使用initailizer_list初始化,就像构建key 和 key1的时候,我们也可以通过重载迭代器的方式,即我们先定义一个容器,可以是list可以是set可以是Vector,构造好了之后,mset直接传入两个的迭代器的就可以了。

然后是mget,使用mget的时候,我们可以看看参数:

它的第二个参数是back_insert_iterator,其实就是尾插迭代器,在STL中,迭代器分为了五种类型,分别是输入迭代器,输出迭代器,前向迭代器,双向迭代器和随机访问迭代器,其中对于back_inserter来说,它就是输出迭代器的一种,mget获取到value之后,就把输出给到这个迭代器对应的容器里面。

那么给的方式,就是看位置了,比如back_inserter对应的位置是尾,那么就相当于给这个容器一直尾插。

它们对应了不同的迭代器,比如back_insert_iterator,insert_iterator,但是我们一般不会直接构造出这几个对象,我们一般会走一些辅助的函数来构造,比如back_inserter。

getrange setrange:

这两个我们如果有了C++string函数的理解,那就非常简单了,无非是我们要确定位置,给个偏移量,然后给上对应的字符串就可以了。

void test_5(Redis &redis)
{redis.flushall();redis.set("key","abcdefghijk");redis.setrange("key",2,"11111111");std::string result = redis.getrange("key",2,-1);std::cout << result << std::endl;
}

incr decr

同理,非常简单,我们直接给代码:

void test_6(Redis &redis)
{redis.flushall();redis.set("key", "20");redis.incr("key");auto value = redis.get("key");if (value)std::cout << value.value() << std::endl;redis.decr("key");value = redis.get("key");if (value)std::cout << value.value() << std::endl;
}

也是非常简单了。

其实文本篇幅较多仅是因为第一次使用Redis对应的API,那么在之后介绍list和hash的时候节奏就会快了。

本文的难点是在mset和mget的时候,如何正确使用迭代器的问题,其他难度相对来说是比较低的。


感谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/77384.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GoogleCodeUtil.java

Google动态验证码实现 GoogleCodeUtil.java package zwf;import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.SecureRandom;/** https://mvnrepository.com/artifact/commons-codec/…

【Leetcode 每日一题】2176. 统计数组中相等且可以被整除的数对

问题背景 给你一个下标从 0 0 0 开始长度为 n n n 的整数数组 n u m s nums nums 和一个整数 k k k&#xff0c;请你返回满足 0 ≤ i < j < n 0 \le i < j < n 0≤i<j<n&#xff0c; n u m s [ i ] n u m s [ j ] nums[i] nums[j] nums[i]nums[j] 且…

如何校验一个字符串是否是可以正确序列化的JSON字符串呢?

方法1&#xff1a;先给一个比较暴力的方法 try {JSONObject o new JSONObject(yourString); } catch (JSONException e) {LOGGER.error("No valid json"); } 方法2&#xff1a; Object json new cn.hutool.json.JSONTokener("[{\"name\":\"t…

【路由交换方向IE认证】BGP选路原则之AS-Path属性

文章目录 一、路由器BGP路由的处理过程控制平面和转发平面选路工具 二、BGP的选路顺序选路的前提选路顺序 三、AS-Path属性选路原则AS-Path属性特性AS-Path管进还是管出呢&#xff1f;使用AS-Path对进本AS的路由进行选路验证AS-Path不接收带本AS号的路由 四、BGP邻居建立配置 一…

2025年热门项目管理软件对比:20款工具详解

本文主要盘点的工具有&#xff1a;1. PingCode; 2. Worktile; 3. Jira; 4. Trello; 5. TAPD; 6. Monday.com; 7. 进度猫; 8. 猪齿鱼; 9. 简道云; 10. Tita项目管理等等20款项目管理软件&#xff08;含免费&#xff09;。 在如今竞争激烈的商业环境中&#xff0c;项目管理软件已…

yaffs_write_new_chunk()函数解析

yaffs_write_new_chunk() 是 YAFFS&#xff08;Yet Another Flash File System&#xff09;文件系统中用于将数据写入新物理块&#xff08;chunk&#xff09;的关键函数。以下是其详细解析&#xff1a; 函数原型 int yaffs_write_new_chunk(struct yaffs_dev *dev, const u8 *…

网络安全-Burp Suite基础篇

声明 本文主要用做技术分享&#xff0c;所有内容仅供参考。任何使用或者依赖于本文信息所造成的法律后果均与本人无关。请读者自行判断风险&#xff0c;并遵循相关法律法规。 1 Burp Suite功能介绍 1.1 Burp Suite 简介 Burp Suite 是一款极为强大且广受欢迎的集成化 …

网络编程 - 2

目录 UDP 数据报套接字编程 API 介绍 DatagramSocket DatagramPacket 补充&#xff1a; 代码示例 - 回显服务器 服务器端&#xff1a; 客户端&#xff1a; 补充&#xff1a; 代码演示 梳理代码&#xff1a; 下面是一个大概的流程图~ 文字解释&#xff1a; 图文并…

【C++深入系列】:模版详解(上)

&#x1f525; 本文专栏&#xff1a;c &#x1f338;作者主页&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客励志语录&#xff1a; 你不需要很厉害才能开始&#xff0c;但你需要开始才能很厉害。 ★★★ 本文前置知识&#xff1a; 类和对象&#xff08;上&#xff09; …

java 设计模式之策略模式

简介 策略模式&#xff1a;策略模式可以定制目标对象的行为&#xff0c;它通过传入不同的策略实现&#xff0c;来配置目标对象的行为。使用策略模式&#xff0c;就是为了定制目标对象在某个关键点的行为。 策略模式中的角色&#xff1a; 上下文类&#xff1a;持有一个策略类…

Perf学习

重要的能解决的问题是这些&#xff1a; perf_events is an event-oriented observability tool, which can help you solve advanced performance and troubleshooting functions. Questions that can be answered include: Why is the kernel on-CPU so much? What code-pa…

「仓颉编程语言」Demo

仓颉编程语言」Demo python 1)# 仓颉语言写字楼管理系统示例&#xff08;虚构语法&#xff09;# 语法规则&#xff1a;中文关键词 类Python逻辑定义 写字楼管理系统属性:租户库 列表.新建()报修队列 列表.新建()费用单价 5 # 元/平方米方法 添加租户(名称, 楼层, 面积):…

锁(Mutex)、信号量(Semaphore)与条件量(Condition Variable)

一、同步机制的核心意义 在多线程/多进程编程中&#xff0c;当多个执行流共享资源&#xff08;如变量、内存、文件&#xff09;时&#xff0c;可能因操作顺序不确定导致数据竞争&#xff08;Data Race&#xff09;。同步机制的作用是&#xff1a; 保证原子性&#xff1a;确保…

前端基础之《Vue(6)—组件基础(2)》

接上一篇。 七、v-model深入学习 <html> <head><title>组件基础-4</title><style>.score {display: inline-block;}.score>span {display: inline-block;width: 25px;height: 25px;background: url(./assets/star.png) center center / 25p…

SQL:聚合函数(Aggregate Functions)

目录 第一性原理出发思考 ——我们为什么需要聚合函数&#xff1f; 什么是聚合函数&#xff1f; 常见聚合函数 实例讲解 &#x1f538; 1. COUNT() —— 计数 &#x1f538; 2. MAX() / MIN() —— 最大 / 最小值 &#x1f538; 3. SUM() —— 求和 &#x1f538; 4. …

海关总署广东:广东外贸一季度进出口2.14万亿元 同期增长4.2%

大湾区经济网湾区财经报道&#xff0c;据海关总署广东分署统计&#xff0c;今年一季度&#xff0c;广东外贸进出口2.14万亿元&#xff0c;较去年同期&#xff08;下同&#xff09;增长4.2%&#xff0c;增速高于全国2.9个百分点。其中&#xff0c;出口1.34万亿元&#xff0c;增长…

MySQL中高级语法

Mysql高级语法 持续更新中… 1、EXISTS语法 一、基本语法结构 SELECT [列名] FROM [主表] WHERE [条件]AND EXISTS (SELECT 1 -- 子查询内容无关&#xff0c;仅需占位符&#xff08;如1、*、X等&#xff09;FROM [子查询表]WHERE [关联条件] -- 必须与外层查询关联&#xf…

SpringBoot 调用deepseek

个人学习心得&#xff0c;仅供参考 软件环境&#xff1a; JDK 17 你用JDK 11 无法支持SpringBoot 3SpringBoot 3 版本以上才支持spring aimavan 3.6.11.获取Deepseek官网的API-key 官网&#xff1a;https://platform.deepseek.com/api_keys 2.创建项目 这样创建 添加依赖…

性能测试面试题的详细解答

以下是性能测试面试题的详细解答&#xff1a; 1. 性能测试的流程是怎样的&#xff1f; 性能测试流程通常包括以下几个步骤&#xff1a; - **需求分析**&#xff1a;明确测试目标、性能指标&#xff08;如响应时间、吞吐量等&#xff09;。 - **环境搭建**&#xff1a;搭建测试环…

C++程序设计基础实验:C++对C的扩展特性与应用

C程序设计基础实验&#xff1a;C对C的扩展特性与应用 &#x1f525; 本文详细讲解C基础实验&#xff0c;包含C对C语言的扩充与增强特性&#xff0c;从零开始掌握函数重载、引用、指针等核心概念&#xff0c;附详细代码分析与运行结果。适合C初学者和有C语言基础想学习C的同学&a…