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

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 后面是分数
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
汽车电动助力转向控制系统的开发全流程通常包括以下步骤: 1. 需求分析:与客户产品经理进行沟通,了解电动助力转向控制系统的功能和性能需求。收集关于转向系统的详细规格和要求,确保对系统有清晰的理解。 2. 系统设计:在需求分析的基础上,进行系统设计。确定系统的整体架构、硬件和软件组件的选择,以及系统的接口和交互设计。考虑到转向系统的安全性、可靠性和性能要求,在设计过程中进行故障排除和维护的便利性。 3. 软件开发:根据系统设计的要求,进行软件编程。使用适当的编程语言(如C、C++)编写软件,实现电动助力转向控制算法、输入输出处理、故障诊断等功能。进行测试和调试,确保软件的正确性和稳定性。 4. 硬件开发:选择合适的硬件平台,设计电路板,选择传感器和执行器等硬件组件。进行电路设计、布线、焊接等工作,确保硬件与软件的互操作性和稳定性。 5. 集成与测试:将软件和硬件组件集成到一个完整的系统中。进行各种功能和性能测试,验证系统是否按照要求工作。这包括对转向系统的动力输出、转向力反馈、故障诊断等方面进行测试和评估。 6. 验证与认证:对系统进行验证和认证,确保系统符合相关标准和要求。进行全面的测试和评估,包括功能、性能、安全性等方面。 7. 生产与部署:准备好投入生产和部署。与制造商合作,确保生产过程符合质量标准,并安装到汽车中。 8. 支持与维护:提供技术支持和维护服务。跟踪系统的性能和可靠性,处理用户反馈和故障报告,确保电动助力转向控制系统的正常运行。 以上是汽车电动助力转向控制系统开发的一般流程,具体的实施可能会因项目和组织而有所不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

季布,

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值