目录
0.准备
1.string
get | set
set_with_timeout_test.cpp
set_nx_xx_test.cpp
mset_test.cpp
mget_test.cpp
getrange_setrange_test.cpp
incr_decr_test.cpp
2.list
lpush_lrange_test.cpp
rpush_test.cpp
lpop_rpop_test.cpp
blpop_test.cpp
llen_test.cpp
0.准备
我们可以先定义了三个模板函数,用于打印不同类型的容器内容。每个函数都接受一个容器作为参数,并根据容器内元素的类型以不同的方式打印它们。
1.printContainer
函数:
template<typename T>
inline void printContainer(const T& container) {
for (const auto& elem : container) {
std::cout << elem << std::endl;
}
}
- 该函数适用于任何包含可以直接输出到
std::cout
的元素的容器(如int
,double
,std::string
等)。 - 它遍历容器中的每个元素,并使用
std::cout
打印每个元素。
2.printContainerPair
函数:
template<typename T>
inline void printContainerPair(const T& container) {
for (auto& elem : container) {
// 此处预期 elem 是一个 std::pair
std::cout << elem.first << ": " << elem.second << std::endl;
}
}
- 这个函数专为存储
std::pair
类型元素的容器设计,比如std::map
或std::unordered_map
中的键值对。 - 对于每个元素,它假设
elem
是一个std::pair
,并打印出pair
的first
和second
成员。
3.printContainerOptional
函数:
template<typename T>
inline void printContainerOptional(const T& container) {
for (const auto& elem : container) {
// 此处预期 elem 是一个 optional 类型的元素, 打印之前, 先判定一下, 看是否有效
if (elem) {
std::cout << elem.value() << std::endl;
} else {
std::cout << "元素无效" << std::endl;
}
}
}
- 此函数针对包含
std::optional
类型元素的容器。 - 在打印之前,它会检查每个
optional
元素是否有效(即是否包含值)。如果有效,则调用value()
方法获取其值并打印;如果无效,则打印“元素无效”。
示例
#include <vector>
#include <map>
#include <optional>
#include <iostream>
// 假设上面的函数已经定义好了
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::map<std::string, int> nameAge = {{"Alice", 30}, {"Bob", 25}};
std::vector<std::optional<int>> optionals = {10, {}, 20, {}};
printContainer(numbers);
printContainerPair(nameAge);
printContainerOptional(optionals);
return 0;
}
运行:
1.string
redis.get()
返回的是一个optional
类型
-
optional
类型在C++14中,正式纳入标准库 - 因为
redis.get()
会返回nil
无效值,用std::string
不方便表现nil
,而std::string*
虽然可以用nullptr
表示无效,但是返回指针又设计内存管理问题 -
所以综上,此处使用
optional
表示"非法值"/“无效值”
get | set
// test1.cpp
#include <iostream>
#include <sw/redis++/redis++.h>
#include "util.hpp"
using namespace std;
using sw::redis::Redis;
void test1(Redis& redis) {
cout << "get 和 set" << endl;
redis.flushall();
redis.set("key", "111");//类命令
auto value = redis.get("key");//接收命令 返回值
if (value) {
cout << "value: " << value.value() << endl;
}
redis.set("key", "222");
value = redis.get("key");
if (value) {
cout << "value: " << value.value() << endl;
}
}
运行:
⭕注意:
1.redis.flushall(); 在 test 开始
- 作用:清空数据库,避免之前残留的数据干扰
2.get return 的 value 取值采取:value.value()
set_with_timeout_test.cpp
这个文件包含了 test2
函数,用于测试带有超时时间的 set
命令。
// set_with_timeout_test.cpp
#include <iostream>
#include <chrono>
#include <thread>
#include <sw/redis++/redis++.h>
using namespace std;
using namespace std::chrono_literals;
using sw::redis::Redis;
void test2(Redis& redis) {
cout << "set 带有超时时间" << endl;
redis.flushall();
redis.set("key", "111", 10s);
this_thread::sleep_for(3s);
long long time = redis.ttl("key");
cout << "time: " << time << endl;
}
set_nx_xx_test.cpp
这个文件包含了 test3
函数,用于测试 set
命令的 NX
和 XX
选项。
// set_nx_xx_test.cpp
#include <iostream>
#include <sw/redis++/redis++.h>
using namespace std;
using sw::redis::Redis;
using sw::redis::UpdateType;
void test3(Redis& redis) {
cout << "set NX 和 XX" << endl;
redis.flushall();
redis.set("key", "111");
// set 的重载版本中, 没有单独提供 NX 和 XX 的版本, 必须搭配过期时间的版本来使用.
redis.set("key", "222", 0s, UpdateType::EXIST);
auto value = redis.get("key");
if (value) {
cout << "value: " << value.value() << endl;
} else {
cout << "key 不存在!" << endl;
}
}
mset_test.cpp
这个文件包含了 test4
函数,用于测试 mset
命令。
注意:
- 可以把多个键值对提前组织到容器 vector<pair<string, string>> 中. 以迭代器的形式告诉 mset
// mset_test.cpp
#include <iostream>
#include <vector>
#include <sw/redis++/redis++.h>
using namespace std;
using sw::redis::Redis;
void test4(Redis& redis) {
cout << "mset" << endl;
redis.flushall();
// 第一种写法, 使用初始化列表描述多个键值对
// redis.mset({ std::make_pair("key1", "111"), std::make_pair("key2", "222"), std::make_pair("key3", "333") });
// 第二种写法, 可以把多个键值对提前组织到容器中. 以迭代器的形式告诉 mset
vector<pair<string, string>> keys = {
{"key1", "111"},
{"key2", "222"},
{"key3", "333"}
};
redis.mset(keys.begin(), keys.end());
auto value = redis.get("key1");
if (value) {
cout << "value: " << value.value() << endl;
}
value = redis.get("key2");
if (value) {
cout << "value: " << value.value() << endl;
}
value = redis.get("key3");
if (value) {
cout << "value: " << value.value() << endl;
}
}
mget_test.cpp
这个文件包含了 test5
函数,用于测试 mget
命令。
// mget_test.cpp
#include <iostream>
#include <vector>
#include <sw/redis++/redis++.h>
#include "util.hpp"
using namespace std;
using sw::redis::Redis;
using sw::redis::OptionalString;
void test5(Redis& redis) {
cout << "mget" << endl;
redis.flushall();
vector<pair<string, string>> keys = {
{"key1", "111"},
{"key2", "222"},
{"key3", "333"}
};
redis.mset(keys.begin(), keys.end());
vector<OptionalString> result;
auto it = back_inserter(result);
redis.mget({"key1", "key2", "key3", "key4"}, it);
printContainerOptional(result);
}
getrange_setrange_test.cpp
这个文件包含了 test6
函数,用于测试 getrange
(return string) 和 setrange
命令。
// getrange_setrange_test.cpp
#include <iostream>
#include <string>
#include <sw/redis++/redis++.h>
using namespace std;
using sw::redis::Redis;
void test6(Redis& redis) {
cout << "getrange 和 setrange" << endl;
redis.flushall();
redis.set("key", "abcdefghijk");
string result = redis.getrange("key", 2, 5);
cout << "result: " << result << endl;
redis.setrange("key", 2, "xyz");
auto value = redis.get("key");
cout << "value: " << value.value() << endl;
}
incr_decr_test.cpp
这个文件包含了 test7
函数,用于测试 incr
和 decr
命令。
// incr_decr_test.cpp
#include <iostream>
#include <sw/redis++/redis++.h>
using namespace std;
using sw::redis::Redis;
void test7(Redis& redis) {
cout << "incr 和 decr" << endl;
redis.flushall();
redis.set("key", "100");
//对比关注 如下两种返回结果
//返回结果1:long long
long long result = redis.incr("key");
cout << "result: " << result << endl;
//返回结果2:对象
auto value = redis.get("key");
cout << "value: " << value.value() << endl;
result = redis.decr("key");
cout << "result: " << result << endl;
value = redis.get("key");
cout << "value: " << value.value() << endl;
}
运行:
2.list
lpush_lrange_test.cpp
这个文件包含了 test1
函数,用于测试 lpush
和 lrange
命令。
// lpush_lrange_test.cpp
#include <iostream>
#include <vector>
#include <string>
#include <sw/redis++/redis++.h>
#include "util.hpp"
using namespace std;
using sw::redis::Redis;
void test1(Redis& redis) {
cout << "lpush 和 lrange" << endl;
redis.flushall();
// 插入单个元素
redis.lpush("key", "111");
// 插入一组元素, 基于初始化列表
redis.lpush("key", {"222", "333", "444"});
// 插入一组元素, 基于迭代器
vector<string> values = {"555", "666", "777"};
redis.lpush("key", values.begin(), values.end());
// lrange 获取到列表中的元素
vector<string> results;//容器
auto it = back_inserter(results);//创建插入迭代器,用于将元素添加到容器的末尾
redis.lrange("key", 0, -1, it);
printContainer(results);
}
关于这个地方迭代器的使用,详细可以看前面两篇博文
- [Redis#11] cpp-redis | 通用命令 | optional | 插入迭代器
- STL 源码剖析 note(这个专栏 还在完善中 后续应该会发)
运行
rpush_test.cpp
这个文件包含了 test2
函数,用于测试 rpush
命令。
// rpush_test.cpp
#include <iostream>
#include <vector>
#include <string>
#include <sw/redis++/redis++.h>
#include "util.hpp"
using namespace std;
using sw::redis::Redis;
void test2(Redis& redis) {
cout << "rpush" << endl;
redis.flushall();
// 插入单个元素
redis.rpush("key", "111");
// 插入多个元素, 基于初始化列表
redis.rpush("key", {"222", "333", "444"});
// 插入多个元素, 基于容器
vector<string> values = {"555", "666", "777"};
redis.rpush("key", values.begin(), values.end());
// 使用 lrange 获取元素
vector<string> results;
auto it = back_inserter(results);
redis.lrange("key", 0, -1, it);
printContainer(results);
}
lpop_rpop_test.cpp
这个文件包含了 test3
函数,用于测试 lpop
和 rpop
命令。
// lpop_rpop_test.cpp
#include <iostream>
#include <optional>
#include <sw/redis++/redis++.h>
using namespace std;
using sw::redis::Redis;
void test3(Redis& redis) {
cout << "lpop 和 rpop" << endl;
redis.flushall();
// 构造一个 list
redis.rpush("key", {"1", "2", "3", "4"});
auto result = redis.lpop("key");
if (result) {
cout << "lpop: " << result.value() << endl;
}
result = redis.rpop("key");
if (result) {
cout << "rpop: " << result.value() << endl;
}
}
如果删除成功了,就打印 .value()
blpop_test.cpp
这个文件包含了 test4
函数,用于测试 blpop
命令。
-
TIPS:对于
std::optional
类型来说,可以直接使用->
访问optional
内部包含的元素的成员
// blpop_test.cpp
#include <iostream>
#include <chrono>
#include <sw/redis++/redis++.h>
using namespace std;
using namespace std::chrono_literals;
using sw::redis::Redis;
void test4(Redis& redis) {
using namespace std::chrono_literals;
cout << "blpop" << endl;
redis.flushall();
auto result = redis.blpop({"key", "key2", "key3"}, 10s);
if (result) {
cout << "key:" << result->first << endl;
cout << "elem:" << result->second << endl;
} else {
cout << "result 无效!" << endl;
}
}
llen_test.cpp
这个文件包含了 test5
函数,用于测试 llen
命令。
return long long
// llen_test.cpp
#include <iostream>
#include <sw/redis++/redis++.h>
using namespace std;
using sw::redis::Redis;
void test5(Redis& redis) {
cout << "llen" << endl;
redis.flushall();
redis.lpush("key", {"111", "222", "333", "444"});
long long len = redis.llen("key");
cout << "len: " << len << endl;
}
对于 接口的返回值,我们可以在 上一篇文章中提到的 文档中查找
为了加深印象 ,和有充裕的时间学习,博主就都测试了一下,下一篇文章 应该会把剩余的常见三种类型测试完,然后 接口调用体会的 汇总,之后要是 用到了,看下一篇文章的总结就好啦~