初識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.pswp.cn/bicheng/77384.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/77384.shtml
英文地址,請注明出處:http://en.pswp.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…