Go 快速开发朋友圈助力项目

news2024/11/15 15:51:16

1.根据业务完成不同功能数据表的设计和编写

在这里插入图片描述

注册功能
在models/user.go中定义结构体 验证用户名是否已存在 添加用户

package models

import (
	"gin-ranking/dao"
	"time"
)

type User struct {
	Id         int    `json:"id"`
	Username   string `json:"username"`
	Password   string `json:"password"`
	AddTime    int64  `json:"addTime"`
	UpdateTime int64  `json:"updateTime"`
}

func (User) TableName() string {
	return "user"
}

func GetUserInfoByUsername(username string) (User, error) {
	var user User
	err := dao.Db.Where("username=?", username).First(&user).Error
	return user, err
}

func AddUser(username string, password string) (int, error) {
	user := User{Username: username, Password: password, AddTime: time.Now().Unix(), UpdateTime: time.Now().Unix()}
	err := dao.Db.Create(&user).Error
	return user.Id, err
}

在 controllers/user.go中编写注册功能接口

package controllers

import (
	"gin-ranking/models"
	"github.com/gin-gonic/gin"
)

type UserController struct {
}

func (u UserController) Register(c *gin.Context) {
	//获取参数信息
	username := c.DefaultPostForm("username", "")
	password := c.DefaultPostForm("password", "")
	confirmPassword := c.DefaultPostForm("confirmPassword", "")
	if username == "" || password == "" || confirmPassword == "" {
		ReturnError(c, 4001, "请输入正确的信息")
		return
	}
	if password != confirmPassword {
		ReturnError(c, 4001, "密码和确认密码不相同")
		return
	}

	user, err := models.GetUserInfoByUsername(username)
	if user.Id != 0 {
		ReturnError(c, 4001, "此用户名已存在")
		return
	}
	_, err = models.AddUser(username, EncyMd5(password))
	if err != nil {
		ReturnError(c, 4002, "注册失败,请重试")
		return
	}

	ReturnSuccess(c, 0, "success", "", 1)
}

controllers/common.go 对密码进行加密

func EncyMd5(s string) string {
	ctx := md5.New()
	ctx.Write([]byte(s))
	return hex.EncodeToString(ctx.Sum(nil))
}

登录

安装

go get -u github.com/gin-contrib/sessions/redis
go get -u github.com/gin-contrib/sessions

登录信息保存在session redis中
config/redis.go

package config

const (
	RedisAddress = "localhost:6379"
)

在这里插入图片描述

controllers/user.go

// 如果直接使用上面的结构体 会将密码也返回  所以这里重新定义一个结构体用以返回
type UserApi struct {
	Id       int    `json:"id"`
	Username string `json:"username"`
}

func (u UserController) Login(c *gin.Context) {
	// 接收用户名和密码
	username := c.DefaultPostForm("username", "")
	password := c.DefaultPostForm("password", "")
	if username == "" || password == "" {
		ReturnError(c, 4001, "请输入用户名和密码")
		return
	}
	user, _ := models.GetUserInfoByUsername(username)
	if user.Id == 0 {
		ReturnError(c, 4004, "用户名或密码不正确")
		return
	}

	if user.Password != EncyMd5(password) {
		ReturnError(c, 4004, "用户名或密码不正确")
		return
	}
	// 用户信息存储到session
	session := sessions.Default(c)
	//Int转换为字符串
	session.Set("login:"+strconv.Itoa(user.Id), user.Id)
	session.Save()
	data := UserApi{Id: user.Id, Username: user.Username}
	ReturnSuccess(c, 0, "登录成功", data, 1)

}

在这里插入图片描述

基于mysql实现投票功能

在这里插入图片描述

首先获取活动参赛选手接口
在这里插入图片描述

点击为他投票获取详情接口
controllers/player.go

package controllers

import (
	"gin-ranking/models"
	"github.com/gin-gonic/gin"
	"strconv"
)

type PlayerController struct{}

func (p PlayerController) GetPlayers(c *gin.Context) {
	aidStr := c.DefaultPostForm("aid", "0")
	aid, _ := strconv.Atoi(aidStr)
	rs, err := models.GetPlayers(aid, "id asc")
	if err != nil {
		ReturnError(c, 4004, "没有相关信息")

		return
	}
	ReturnSuccess(c, 0, "success", rs, 1)
}

models/player.go

package models

import (
	"gin-ranking/dao"
	"github.com/jinzhu/gorm"
)

type Player struct {
	Id          int    `json:"id"`
	Aid         int    `json:"aid"`
	Ref         string `json:"ref"`
	Nickname    string `json:"nickname"`
	Declaration string `json:"declaration"`
	Avatar      string `json:"avatar"`
	Score       int    `json:"score"`
	//AddTime     int64  `json:"addTime"`
	//UpdateTime  int64  `json:"updateTime"`
}

func (Player) TableName() string {
	return "player"
}

func GetPlayers(aid int, sort string) ([]Player, error) {
	var players []Player
	err := dao.Db.Where("aid = ?", aid).Order(sort).Find(&players).Error
	return players, err
}

router/routers.go

player := r.Group("/player")
	{
		player.POST("/list", controllers.PlayerController{}.GetPlayers)
	}

投票功能

controllers/vote.go

package controllers

import (
	"gin-ranking/models"
	"github.com/gin-gonic/gin"
	"strconv"
)

type VoteController struct{}

func (v VoteController) AddVote(c *gin.Context) {
	userIdStr := c.DefaultPostForm("userId", "0")
	playerIdStr := c.DefaultPostForm("playerId", "0")
	userId, _ := strconv.Atoi(userIdStr)
	playerId, _ := strconv.Atoi(playerIdStr)

	if userId == 0 || playerId == 0 {
		ReturnError(c, 4001, "请输入正确的信息")
		return
	}
	user, _ := models.GetUserInfo(userId)
	if user.Id == 0 {
		ReturnError(c, 4001, "投票用户不存在")
		return
	}
	player, _ := models.GetPlayerInfo(playerId)
	if player.Id == 0 {
		ReturnError(c, 4001, "选手不存在")
		return
	}
	vote, _ := models.GetVoteInfo(userId, playerId)
	if vote.Id != 0 {
		ReturnError(c, 4001, "已投票")
		return
	}

	rs, err := models.AddVote(userId, playerId)
	if err == nil {
		//更新选手票数 自增1
		models.UpdatePlayerScore(playerId)
		//更新redis
		//var redisKey string
		//redisKey = "ranking:" + strconv.Itoa(player.Aid)
		//cache.Rdb.ZIncrBy(cache.Rctx, redisKey, 1, strconv.Itoa(playerId))
		ReturnSuccess(c, 0, "success", rs, 1)
		return
	}
	ReturnError(c, 4004, "请联系管理员")
}

models/vote.go

package models

import (
	"gin-ranking/dao"
	"time"
)

type Vote struct {
	Id       int   `json:"id"`
	UserId   int   `json:"userId"`
	PlayerId int   `json:"playerId"`
	AddTime  int64 `json:"addTime"`
}

func (Vote) TableName() string {
	return "vote"
}

func AddVote(userId int, playerId int) (int, error) {
	vote := Vote{UserId: userId, PlayerId: playerId, AddTime: time.Now().Unix()}
	err := dao.Db.Create(&vote).Error
	return vote.Id, err
}

func GetVoteInfo(userId int, playerId int) (Vote, error) {
	var vote Vote
	err := dao.Db.Where("user_id = ? AND player_id = ?", userId, playerId).First(&vote).Error
	return vote, err
}

router/routers.go

vote := r.Group("/vote")
	{
		vote.POST("/add", controllers.VoteController{}.AddVote)
	}

models/user.go

func GetUserInfo(id int) (User, error) {
	var user User
	err := dao.Db.Where("id = ?", id).First(&user).Error
	return user, err
}

models/player.go

func GetPlayerInfo(id int) (Player, error) {
	var player Player
	err := dao.Db.Where("id = ?", id).First(&player).Error
	return player, err
}

models/player.go

func UpdatePlayerScore(id int) {
	var player Player
	dao.Db.Model(&player).Where("id = ?", id).UpdateColumn("score", gorm.Expr("score + ?", 1))
}

基于mysql数据库orderby排序实现排名展示功能

controllers/player.go

func (p PlayerController) GetRanking(c *gin.Context) {
	aidStr := c.DefaultPostForm("aid", "0")
	aid, _ := strconv.Atoi(aidStr)
	rs, err := models.GetPlayers(aid, "score desc")
	if err != nil {
		ReturnError(c, 4004, "没有相关信息")
		return
	}
	ReturnSuccess(c, 0, "success", rs, 1)
	return
}

modesl/player.go

func GetPlayers(aid int, sort string) ([]Player, error) {
	var players []Player
	err := dao.Db.Where("aid = ?", aid).Order(sort).Find(&players).Error
	return players, err
}
r.POST("/ranking", controllers.PlayerController{}.GetRanking)

使用redis的有序集合 Sorted Sets优化排行榜功能

go get -u github.com/redis/go-redis/v9

controllers/player.go

package controllers

import (
	"gin-ranking/cache"
	"gin-ranking/models"
	"github.com/gin-gonic/gin"
	"strconv"
	"time"
)

type PlayerController struct{}

func (p PlayerController) GetPlayers(c *gin.Context) {
	aidStr := c.DefaultPostForm("aid", "0")
	aid, _ := strconv.Atoi(aidStr)
	rs, err := models.GetPlayers(aid, "id asc")
	if err != nil {
		ReturnError(c, 4004, "没有相关信息")

		return
	}
	ReturnSuccess(c, 0, "success", rs, 1)
}

func (p PlayerController) GetRanking(c *gin.Context) {
	aidStr := c.DefaultPostForm("aid", "0")
	aid, _ := strconv.Atoi(aidStr)

	var redisKey string
	// 通过aid区分活动
	redisKey = "ranking:" + aidStr
	// 这段代码是使用 Go 语言操作 Redis 数据库,通过 ZRevRange 方法获取有序集合中指定范围内的成员,并按照分数从大到小排序。其中,redisKey 是有序集合的键名,0 和 -1 分别表示起始位置和结束位置,-1 表示最后一个成员。

	rs, err := cache.Rdb.ZRevRange(cache.Rctx, redisKey, 0, -1).Result()
	// 如果有就直接返回
	if err == nil && len(rs) > 0 {
		var players []models.Player
		for _, value := range rs {
			id, _ := strconv.Atoi(value)
			rsInfo, _ := models.GetPlayerInfo(id)
			if rsInfo.Id > 0 {
				players = append(players, rsInfo)
			}
		}
		ReturnSuccess(c, 0, "success", players, 1)
		return
	}
	// 如果没有就直接从数据库获取
	rsDb, errDb := models.GetPlayers(aid, "score desc")
	//获取到值
	if errDb == nil {
		// 从mysql数据库获取到的值再存入到redis中
		for _, value := range rsDb {
			cache.Rdb.ZAdd(cache.Rctx, redisKey, cache.Zscore(value.Id, value.Score)).Err()
		}
		//遍历完成以后为rediskey设置过期时间
		cache.Rdb.Expire(cache.Rctx, redisKey, 24*time.Hour)
		ReturnSuccess(c, 0, "success", rs, 1)
		return
	}
	ReturnError(c, 4004, "没有相关信息")
	return
}

cache/redis.go

package cache

import (
	"context"
	"gin-ranking/config"
	"github.com/redis/go-redis/v9"
)

var (
	Rdb  *redis.Client
	Rctx context.Context
)

func init() {
	Rdb = redis.NewClient(&redis.Options{
		Addr:     config.RedisAddress,
		Password: config.RedisPassword, // 没有密码,默认值
		DB:       config.RedisDb,       // 默认DB 0
	})
	Rctx = context.Background()
}

func Zscore(id int, score int) redis.Z {
	return redis.Z{Score: float64(score), Member: id}
}

config/redis.go

package config

const (
	RedisAddress  = "localhost:6379"
	RedisPassword = "123456"
	RedisDb       = 0
)

问题:当我们投票的时候,我们更新的是数据库,这个时候如果不更新redis,在缓存没有过期的这个时间段,它的排行榜是不变的,所以要优化一下投票的代码
在这里插入图片描述

前面是参赛选手的id 后面是分数
在这里插入图片描述

在这里插入图片描述

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

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

相关文章

面包屑对格林童话里的兄妹没有帮助,但对你的网站有

早上看产研周报的时候瞄到一眼「面包屑」三个字,因为是个面包脑袋,所以快速识别到了这几个字,在我的认知里,面包屑和 Bytebase 好像并不对付? 其实这里说的是面包屑导航啦,加上图是不是容易理解一点&#x…

Linux进阶-加深进程印象

进程 进程状态转换 一般来说,一个进程的开始都是从其父进程调用fork()函数开始,所以在系统一上电运行时,init进程就开始工作,在系统运行过程中,会不断启动新的进程(要么由init进程启动,要么由被…

Floyd-Warshall最短路径(C++,例题:pta大众情人)

Floyd-Warshall算法是一种用于求解所有点对之间最短路径的动态规划算法。它可以处理带权有向图或无向图,但是不能处理带负环的图。 算法步骤如下: 1. 初始化一个nn的矩阵D,其中D[i][j]表示从顶点i到顶点j的最短路径长度,如果i和…

文心一言 VS 讯飞星火 VS chatgpt (111)-- 算法导论10.2 2题

二、用go语言,用一个单链表 L实现一个栈。要求操作 PUSH和 POP 的运行时间仍为 O(1)。 文心一言: 在 Go 语言中,我们可以用结构体来实现一个单链表,然后再用栈的相关操作。 以下是一个可能的实现方式: package mai…

Spring Boot 中的 Redis 数据操作配置和使用

Spring Boot 中的 Redis 数据操作配置和使用 Redis(Remote Dictionary Server)是一种高性能的开源内存数据库,用于缓存、消息队列、会话管理和数据存储。在Spring Boot应用程序中,Redis被广泛用于各种用例,包括缓存、…

从0开始学Java:Java概述

文章目录 1. JavaSE体系介绍2. 计算机语言介绍3. Java语言概述3.1 Java生态圈3.2 Java语言发展历史3.3 Java技术体系平台3.4 Java的主要应用领域3.5 Java语言的特点 4. Java语言跨平台原理 1. JavaSE体系介绍 JavaSE知识模块介绍 第一部分:计算机编程语言核心结构&…

2023 年诺贝尔物理学奖-阿秒光谱学

如果您想了解和衡量周围的世界,您可以使用的最重要的工具之一就是能够准确地对正在发生的事情进行成像(或拍摄快照)。在 19 世纪,摄影意味着让拍摄对象保持完全静止,同时积累大量光线:相当于几秒钟的时间。…

一种用于肽图分析的烷化剂,Desthiobiotin-Iodoacetamide

中文名:脱硫生物素-碘乙酰胺 英文名:Desthiobiotin-Iodoacetamide 化学式:C14H25IN4O3 分子量:424.28 外观:固体/粉末 规格:10mg、25mg、50mg等(接受各种规格的定制服务,具体可…

JavaScript的懒加载处理

😘博主:小猫娃来啦 😘文章核心:JavaScript的懒加载处理 文章目录 什么是懒加载实现懒加载的方式js四步法设置占位图监听滚动事件加载图片触发加载函数 什么是懒加载 懒加载(Lazy Loading)是一种优化技术&a…

GitLab 502问题解决方案

由于最近 gitlab 切换到另一台服务器上部署的 gitlab 后,经常出现 502。平时重启 gitlab 后都能解决,今天突然重启多次后都还是 502(重启日志是正常的),遂通过 gitlab-ctl tail 查看日志进行排查。 gitlab-ctl tail通…

《进化优化》第3章 遗传算法

文章目录 3.1 遗传学的历史3.2 遗传学3.3 遗传学的历史3.4 一个简单的二进制遗传算法3.4.1 用于机器人设计的遗传算法3.4.2 选择与交叉3.4.3 变异3.4.5 遗传算法参数调试 3.5 简单的连续遗传算法 遗传算法模仿自然选择来解决优化问题。 为研究遗传算法,得遵守自然选…

微软10月补丁 | 修复103个漏洞,包括2个零日漏洞,13个严重漏洞

近日,微软发布了2023年10月的补丁更新,解决了其软件中的103个漏洞。 在这103个漏洞中,有13个的评级为严重漏洞,90个被评为重要漏洞。自9月12日以来,谷歌已经解决了基于chrome的Edge浏览器的18个安全漏洞。 这两个零日…

ATFX汇市:美国9月CPI数据来袭,机构预期年率增速将继续回落

ATFX汇市:今日20:30,美国劳工部将公布9月未季调CPI年率增速,前值为3.7%,预期值3.6%;9月未季调核心CPI年率,同一时间公布,前值为4.3%,预期值4.1%。无论是名义CPI增速还是核心CPI增速&…

深入理解强化学习——标准强化学习和深度强化学习

分类目录:《深入理解强化学习》总目录 强化学习的历史 早期的强化学习,我们称其为标准强化学习。最近业界把强化学习与深度学习结合起来,就形成了深度强化学习(Deep ReinforcemetLearning)。因此,深度强化…

基于YOLO算法的单目相机2D测量(工件尺寸和物体尺寸)三

1.简介 1.1 2D测量技术 基于单目相机的2D测量技术在许多领域中具有重要的背景和意义。 工业制造:在工业制造过程中,精确测量是确保产品质量和一致性的关键。基于单目相机的2D测量技术可以用于检测和测量零件尺寸、位置、形状等参数,进而实…

腾讯云国际站-阿里云OSS如何迁移到腾讯云COS?腾讯云cos迁移教程

下面小编将介绍当源对象存储部署在阿里云国际版OSS 时,如何配置全托管迁移任务和半托管迁移任务,实现顺利迁移数据至腾讯云国际版COS。 准备工作 阿里云对象存储 OSS 创建 RAM 子账号并授予相关权限: 登录 RAM 控制台。选择人员管理 > …

吃瓜神奇!企查查、天眼查、天眼销,到底哪家强?

最近,我发现很多人在讨论查企业信息的工具,什么企查查、天眼查、天眼销等,到底哪家强呢? 首先,我们来简单了解一下这些工具。企查查是一款可以帮助用户查询企业信息的工具,通过输入关键词,可以搜…

VPN基础

1.VPN简介 VPN即虚拟专用网,泛指通过VPN技术在公用网络上构建的虚拟专用网络。VPN用户在此虚拟网络中传输私网流量,在不改变网络现状的情况下实现安全、可靠的连接。 专用:VPN网络是专门供VPN用户使用的网络,对于VPN用户&#xf…

Redis魔法:点燃分布式锁的奇妙实现

分布式锁是一种用于在分布式系统中控制对共享资源的访问的锁。它与传统的单机锁不同,因为它需要在多个节点之间协调以确保互斥访问。 本文将介绍什么是分布式锁,以及使用Redis实现分布式锁的几种方案。 一、前言 了解分布式锁之前,需要先了…

太顶了!文心大模型落地文旅行业不仅能业生成潮玩、还可补文物残卷!

10月11日,文化和旅游部公布了2023年文化和旅游数字化创新示范十佳案例和优秀案例。百度文心大模型创新文化产品生产方式入选十佳案例,也是唯一一个入选的大模型应用案例。文心大模型获奖类型为运用数字化工具助力艺术创作生产,促进文化机构数…