【Gin-Web】Bluebell社區項目梳理5:投票功能分析與實現

本文目錄

  • 一、投票功能
    • 投票流程
    • 實現代碼
    • redis投票

一、投票功能

投票流程

首先我們要明確,就是 誰(哪個用戶:userID)哪個帖子(postID) 投了 什么票(贊成票or反對票)。

贊成票越多,熱度越高,就會越展示在前面。

在redis中可以用zset存儲帖子,那么有兩種存儲方式。

一是根據帖子的發布時間存儲帖子(根據時間戳來,時間越新,時間戳越大,越在前面),或者是按照評分來存儲帖子。

在這里插入圖片描述

然后還可以設計一個zset,用來存儲給某個帖子投票用戶。哪個用戶投了贊成票就記為+1,投了反對票就記為-1。

在這里插入圖片描述

所以總的來設計了一個帖子算法,投一張贊成票就加對應的分數,比如400分。

時間戳+贊成票*400分=評分,評分越高越放前面。

實現代碼

首先我們封裝了投票數據的結構體。

在這里插入圖片描述

然后是controller層。

在這里插入圖片描述
然后就是具體投票的業務邏輯實現部分Logic.VoteForPost

strconv.Itoa 是一個函數,用于將整數轉換為字符串。它要求輸入必須是 int 類型,因此這里使用了 int(userId) 將 userId 轉換為 int。將用戶 ID 轉換為字符串格式,因為 Redis 的鍵通常是以字符串形式存儲的。

在這里插入圖片描述

redis投票

來看看投票的情況:

v=1時,有兩種情況1.之前沒投過票,現在要投贊成票		 --> 更新分數和投票記錄	差值的絕對值:1	+4322.之前投過反對票,現在要改為贊成票	 --> 更新分數和投票記錄	差值的絕對值:2	+432*2v=0時,有兩種情況1.之前投過反對票,現在要取消			 --> 更新分數和投票記錄	差值的絕對值:1	+4322.之前投過贊成票,現在要取消			 --> 更新分數和投票記錄	差值的絕對值:1	-432v=-1時,有兩種情況1.之前沒投過票,現在要投反對票		 --> 更新分數和投票記錄	差值的絕對值:1	-4322.之前投過贊成票,現在要改為反對票	 --> 更新分數和投票記錄	差值的絕對值:2	-432*2

除此之外,我們還有對投票的限制:

每個帖子自發起之日起,一個星期之內允許用戶投票,超過一個星期就不允許投票了。同時到期之后將redis中保存的贊成票數及反對票數存儲到mysql表中。到期之后刪除 KeyPostVotedZSetPrefix

這里的 KeyPostVotedZSetPrefix 就是記錄用戶及投票類型。

在這里插入圖片描述

我們來看看redis.go的相關代碼,其中client就是redis客戶端。

在這里插入圖片描述
service層中,設置了相關的邏輯代碼,來看看處理流程。

首先我們需要去redis中獲取帖子的發布時間,從client中拿即可。并檢查當前時間與帖子發布時間的差值是否超過一周(OneWeekInSeconds)。如果超過一周,返回錯誤 ErrorVoteTimeExpire,表示投票已過期。

在這里插入圖片描述

我們在redis的目錄路徑下,封裝了error錯誤,聲明了幾個自定義錯誤變量。這些錯誤變量用于在 Redis 相關的操作中表示特定的錯誤情況。errors.New 是一個常用的error函數,用于創建一個新的錯誤對象。

通過定義全局的錯誤變量,為 Redis 相關的操作提供了一致的錯誤處理機制。使用 errors.New 創建的錯誤對象可以在整個包中復用,避免了重復創建相同的錯誤信息,提高了代碼的可維護性和一致性。

比如當投票時間已經過期了,我們就需要返回投票過期的錯誤。
在這里插入圖片描述


postTime := client.ZScore(KeyPostTimeZSet, postID).Val()

ZScore 方法查詢帖子 ID 對應的分數(發布時間),并通過 Val() 方法獲取該分數的實際值。返回的 postTime 是一個浮點數,表示帖子的發布時間(通常是 Unix 時間戳)。

ZScore 是 Redis 客戶端提供的一個方法,用于從有序集合(ZSet)中獲取某個成員的分數。它的簽名通常是:

func (c *Client) ZScore(key string, member string) *FloatCmd

key:有序集合的鍵名(唯一標識:鍵名是 Redis 數據庫中唯一標識有序集合的字符串。通過鍵名,你可以訪問和操作特定的有序集合。)

member:有序集合中的成員(在這里是帖子的 ID)。

在剛剛我們有提到,const KeyPostTimeZSet = "bluebell:post:time",這是一個常量,定義了存儲帖子發布時間的有序集合的鍵名。


然后就是更新帖子分數,注意更新帖子分數+記錄用戶為該帖子投票的數據 是要放在一個redis事務中完成的。

在 Redis 中,Pipeline(管道) 是一種用于將多個命令發送到服務器的技術,而 事務(Transaction) 是一種將多個命令打包并一次性執行的機制。在 Redis 的上下文中,Pipeline 和事務經常結合使用,以提高性能和確保操作的原子性

事務 是一種將多個命令打包,并一次性、順序地執行的機制。Redis 的事務通過 MULTI、EXEC、DISCARD 和 WATCH 命令實現。事務的主要特點包括:事務中的所有命令要么全部執行,要么全部不執行。這確保了操作的原子性,避免了部分執行導致的數據不一致問題。事務中的命令會按照順序執行,不會被其他客戶端的命令打斷。

在這里插入圖片描述

KeyPostVotedZSetPrefix    = "bluebell:post:voted:" // zset;記錄用戶及投票類型;參數是post_id

剛剛我們定義了redis的常量,所以我們需要進行下面的操作:

	key := KeyPostVotedZSetPrefix + postIDov := client.ZScore(key, userID).Val()

也就是從 redis中獲取 某個帖子 的 用戶投票類型,根據用戶ID來獲取Val值。

也就是下面這個圖所示:
在這里插入圖片描述

	ov := client.ZScore(key, userID).Val()// 更新:如果這一次投票的值和之前保存的值一致,就提示不允許重復投票if v == ov {return ErrVoteRepested}var op float64if v > ov {op = 1} else {op = -1}diffAbs := math.Abs(ov - v)                                                        // 計算兩次投票的差值pipeline := client.TxPipeline()                                                    // 事務操作_, err = pipeline.ZIncrBy(KeyPostScoreZSet, VoteScore*diffAbs*op, postID).Result() // 更新分數

通過Redis事務來更新分數。

TxPipeline() 是 Redis 客戶端提供的一個方法,用于創建一個事務性 Pipeline。這個 Pipeline 允許將多個命令打包在一起,并作為一個事務發送到 Redis 服務器。

ZIncrBy 是 Redis 的一個命令,用于在有序集合(ZSet)中增加某個成員的分數。

	if v == 0 {_, err = client.ZRem(key, userID).Result()} else {pipeline.ZAdd(key, redis.Z{ // 記錄已投票Score:  v, // 贊成票還是反對票Member: userID,})}_, err = pipeline.Exec()  //執行pipeline中的所有命令

如果v=0,那么從有序集合中移除指定的成員。

client.ZRem:Redis 客戶端提供的方法,用于從有序集合中移除指定的成員。

pipeline.ZAdd:Redis 客戶端提供的方法,用于將一個成員及其分數添加到有序集合中。這里使用了事務性 Pipeline,確保操作的原子性。

redis.Z:一個結構體,包含成員(Member)和分數(Score)。
Score:用戶的投票值(v),表示贊成票(1)或反對票(-1)。
Member:用戶的唯一標識符(userID)。


在 Redis 中,有序集合(ZSet)相關的命令都以 Z 開頭,例如 ZADD、ZSCORE、ZINCRBY、ZREM 等。

Redis 的有序集合命令都以 Z 開頭,例如:
ZADD:將一個或多個成員及其分數添加到有序集合中。
ZSCORE:獲取有序集合中成員的分數。
ZINCRBY:增加有序集合中成員的分數。
ZREM:從有序集合中移除成員。


可以看到,再投出一票之后,在原先的redis基礎上加了432分。

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/896163.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/896163.shtml
英文地址,請注明出處:http://en.pswp.cn/news/896163.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

XUnity.AutoTranslator-deepseek——調用騰訊的DeepSeek V3 API,實現Unity游戲中日文文本的自動翻譯

XUnity.AutoTranslator-deepseek 本項目通過調用騰訊的DeepSeek V3 API,實現Unity游戲中日文文本的自動翻譯。 準備工作 1. 獲取API密鑰 訪問騰訊云API控制臺申請DeepSeek的API密鑰(限時免費)。也可以使用其他平臺提供的DeepSeek API。 …

Python爬蟲-批量爬取股票數據貓各股票代碼

前言 本文是該專欄的第47篇,后面會持續分享python爬蟲干貨知識,記得關注。 本文筆者以股票數據貓為例子,基于Python爬蟲,批量獲取各股票代碼數據。 具體實現思路和詳細邏輯,筆者將在正文結合完整代碼進行詳細介紹。廢話不多說,下面跟著筆者直接往下看正文詳細內容。(附…

《Keras 3 :使用 Vision Transformers 進行物體檢測》:此文為AI自動翻譯

《Keras 3 :使用 Vision Transformers 進行物體檢測》 作者:Karan V. Dave 創建日期:2022 年 3 月 27 日最后修改時間:2023 年 11 月 20 日描述:使用 Vision Transformer 進行對象檢測的簡單 Keras 實現。 (i) 此示例使用 Keras 3 在 Colab 中查看 GitHub 源 介紹 A…

vue-treeselect顯示unknown的問題及解決

問題 解決辦法 去node-modules包里面找到這個組件的源碼,在它dist文件里面找到這個文件,然后搜索unknown,把它刪掉就可以解決了。

深入剖析抽象工廠模式:設計模式中的架構利器

深入剖析抽象工廠模式:設計模式中的架構利器 在軟件開發領域,設計模式是解決常見問題的通用方案,而抽象工廠模式作為創建型設計模式的重要一員,在構建復雜軟件系統時發揮著關鍵作用。它為創建一系列相關或相互依賴的對象提供了一…

python獲取網頁內容 靠譜的做法

獲取網頁內容 response requests.get(url, verifyFalse) 通過這種方式下載網址不太靠譜, 容易出 ssl錯誤 requests.exceptions.SSLError: HTTPSConnectionPool(hostagri.hainan.gov.cn, port443): Max retries exceeded with url: /hnsnyt/xxgk/gfxwj/index_1.html (Caused by…

MFC中CString的Format、與XML中的XML_SETTEXT格式化注意

1、在MFC中導入 "msxml6.dll",并使用其中的XML_SETTEXT函數,此調用在進行格式化的時候,調用的還是CString.Format()函數! 2、用double類型的數據,格式化整形數%d之前,必須將double強轉為int&…

Linux-C-函數棧-SP寄存器

sp(Stack Pointer,棧指針)是計算機體系結構中一個非常重要的寄存器,下面將詳細介紹其作用和原理。 作用 1. 管理棧內存 棧是一種后進先出(LIFO,Last In First Out)的數據結構,在程…

從零開始用react + tailwindcs + express + mongodb實現一個聊天程序(一)

項目包含5個模塊 1.首頁 (聊天主頁) 2.注冊 3.登錄 4.個人資料 5.設置主題 一、配置開發環境 建立項目文件夾 mkdir chat-project cd chat-project mkdir server && mkdir webcd server npm init cd web npm create vitelatest 創建前端項目時我們選擇javascrip…

深入理解 QObject的作用

QObject 作為 Qt 庫中所有對象的基類,其地位無可替代。幾乎 Qt 框架內的每一個類,無論是負責構建用戶界面的 QWidget,還是專注于數據處理與呈現的 QAbstractItemModel,均直接或間接繼承自 QObject。這種繼承體系賦予 Qt 類庫高度的…

22爬蟲:使用Drission Page的兩個案例

案例一:使用DrissionPage抓取BOSS上的招聘信息 使用requests獲取BOSS網站上的內容是非常困難的,但是通過網頁自動化工具DrissionPage或者是Playwright或者是Seleenium是非常容易的,接下來我們就給出使用DrissionPage爬取BOSS網站python招聘的…

Ubuntu 下 nginx-1.24.0 源碼分析 - ngx_atoi 函數

ngx_atoi 聲明在 src/core/ngx_string.h ngx_int_t ngx_atoi(u_char *line, size_t n); 定義在 src/core/ngx_string.c ngx_int_t ngx_atoi(u_char *line, size_t n) {ngx_int_t value, cutoff, cutlim;if (n 0) {return NGX_ERROR;}cutoff NGX_MAX_INT_T_VALUE / 10;cutlim…

具有整合各亞專科醫學領域知識能力的AI智能體開發綱要(2025版)

整合各亞專科醫學領域知識能力的AI代理的開發與研究 一、引言 1.1 研究背景 在科技飛速發展的當下,人工智能(AI)已成為推動各行業變革的關鍵力量,醫療領域也不例外。近年來,AI 在醫療行業的應用取得了顯著進展,從醫學影像診斷到疾病預測,從藥物研發到個性化醫療,AI 技…

如何設計app測試用例

功能測試 測試方法:等價類劃分法、邊界值法、場景法、因果圖法。優先級設定:核心業務功能設為高優先級。需求覆蓋 正向場景、反向場景、關聯接口串場景 與后端開發確認測試用例是否全面覆蓋后端邏輯。和產品確認用例是否覆蓋本次需求,以及是否…

YOLO11 【四】 【DNF制作自己的數據集,切割視頻以及labelimg 閃退問題】

一、問題labelimg 閃退 一點w打標 labelimg就閃退 **原因 : python 版本太高 ** 解決辦法:單獨創建一個虛擬環境用于打標 conda create -n labelimg python3.9 二、使用python腳本切割視頻 # -*- coding: utf-8 -*- import cv2 import osdef video_…

[MDM 2024]Spatial-Temporal Large Language Model for Traffic Prediction

論文網址:[2401.10134] Spatial-Temporal Large Language Model for Traffic Prediction 論文代碼:GitHub - ChenxiLiu-HNU/ST-LLM: Official implementation of the paper "Spatial-Temporal Large Language Model for Traffic Prediction" …

k2路由器登錄校園網

教程1刷入Breed,并手動刷入Padavan固件:斐訊K1、K2、K2P 刷機、刷入Breed 輔助工具 | tb (tbvv.net) Padavan下載網址: 我用的是: Padavan 登錄的網址是 192.168.123.1 Padavan配置教程: 先用網線連上校園網&#…

多源 BFS 算法詳解:從原理到實現,高效解決多源最短路問題

多源 BFS 是一種解決 邊權為 1 的多源最短路問題 的高效算法。其核心思想是將所有源點視為一個“超級源點”,通過一次 BFS 遍歷即可計算所有節點到最近源點的最短距離。以下從原理、實現和代碼示例三個方面深入講解: 目錄 一、原理分析 1. 單源 BFS vs…

【藍橋杯集訓·每日一題2025】 AcWing 6123. 哞叫時間 python

6123. 哞叫時間 Week 1 2月18日 農夫約翰正在試圖向埃爾茜描述他最喜歡的 USACO 競賽,但她很難理解為什么他這么喜歡它。 他說「競賽中我最喜歡的部分是貝茜說 『現在是哞哞時間』并在整個競賽中一直哞哞叫」。 埃爾茜仍然不理解,所以農夫約翰將競賽以…

C++,設計模式,【工廠方法模式】

文章目錄 如何用汽車生產線理解工廠方法模式?一、傳統生產方式的困境二、工廠方法模式解決方案三、模式應用場景四、模式優勢分析五、現實應用啟示?C++,設計模式,【目錄篇】 如何用汽車生產線理解工廠方法模式? 某個早晨,某車企CEO看著會議室里堆積如面的新車訂單皺起眉…