Gin框架简易搭建(5)——项目总述与感悟

说明

项目的初步重构已经完成(具体功能可以参考"实现功能"部分)项目地址。

这个项目的后端设计分为三种类型:创建、删除和更新,实际上更侧重Gorm和数据库的使用,我认为这个项目是一个更类似于Java类的项目,毕竟Go的简单项目给人的印象是更倾向于去使用并发编程来构建群聊等实时通信功能的。但我认为,在对于web开发,前后端交互以及端口监听等知识还模棱两可的时候,选择这样一个更偏向本地数据库类型的项目,可能更容易上手和体验Go开发的乐趣。

有些偷懒的是,这个项目考虑到的信息交互并未使用令牌来确保数据传输的安全,我砍掉了redis的部分。我们使用的是name+password的方式,可以在前端存储登陆之后的用户的name+password,并且和之后需要执行的操作一起返回给后端。

实现功能

路由实现

首先,使用路由的形式展示整体项目的结构功能

用户

user := r.Group("/user"){// 注册用户相关的路由 username password confirm_passworduser.POST("/register", controllers.UserController{}.Register)// 登录用户相关的路由 username passworduser.POST("/login", controllers.UserController{}.Login)//实现投票功能的路由 activity_id username password player_iduser.POST("/vote", controllers.VoteController{}.AddVote)//删除投票功能的路由 activity_id username password player_iduser.POST("/delete_vote", controllers.VoteController{}.DeleteVote)//实现删除用户的路由 username password confirm_sentenceuser.POST("/delete", controllers.UserController{}.UserDelete)// 实现用户获取自己的投票记录 username passworduser.POST("/get_vote_list", controllers.UserController{}.GetVoteList)//实现用户修改密码 username password new_password confirm_new_passworduser.POST("/modify_password", controllers.UserController{}.ModifyPassword)}

参赛者

player := r.Group("/player"){//注册参赛者相关的路由 nickname password confirm_passwordplayer.POST("/register", controllers.PlayerController{}.PlayerRegister)//实现用户选择自己想参与的活动  activity_id nickname passwordplayer.POST("/add_activity", controllers.PlayerController{}.PlayerChooseActivity)//实现添加自己的参赛宣言功能 declaration nickname passwordplayer.POST("/add_declaration", controllers.PlayerController{}.UpdateDeclaration)//获取目前可以参加的活动列表 GETplayer.GET("/get_activitys", controllers.ActivityController{}.GetActivityListForPlayer)//退出正在参与的活动 nickname passwordplayer.POST("/quit_activity", controllers.PlayerController{}.QuitActivity)注销参赛者 和删除用户逻辑一样,不写了//player.POST("/delete", controllers.PlayerController{}.PlayerDelete)//获取给自己投票的玩家列表 nickname passwordplayer.POST("/get_vote_players", controllers.PlayerController{}.GetVoteUsers)//获取某个活动中给自己投票的玩家列表 nickname password activity_idplayer.POST("/get_vote_players_in_activity", controllers.PlayerController{}.GetVoteUsersInActivity)//获取某项活动的排行榜 activity_id 不合理(获取的是总分)player.POST("/get_activity_ranking", controllers.PlayerController{}.GetRanking)}

管理员

controller := r.Group("/admin"){//注册管理员相关的路由 admin_name password confirm_password keycontroller.POST("/register", controllers.Controller{}.Register)//添加 admin_name passwordcontroller.POST("/activity", controllers.Controller{}.AddActivity)//获取参赛者的总分列表 admin_name password activity_namecontroller.POST("/ranking", controllers.Controller{}.GetAllRanking) //获取排行榜 方便下一步去更改某个player的分数//更新某个player的分数 player_name admin_name password update_scorecontroller.POST("/update_score", controllers.Controller{}.UpdatePlayersScore)//将某个活动关闭 admin_name password activity_idcontroller.POST("/close_activity", controllers.Controller{}.CloseActivity)//去除某个参赛者在某项活动的得分 admin_name password activity_id player_idcontroller.POST("/delete_player_score", controllers.Controller{}.DeletePlayerScore)//去除某个用户对于某个活动的投票 admin_name password activity_id user_idcontroller.POST("/delete_vote", controllers.Controller{}.DeleteVote)}

活动

activity := r.Group("/activity"){//获取所有活动列表 GETactivity.GET("/list", controllers.ActivityController{}.GetActivityList)//获取参与某项活动的参赛者列表 activity_idplayer.POST("/player_list", controllers.PlayerController{}.GetPlayerList)}

返回值说明

用户

注册
{"code": 0,"data": {"username": "ht","userid": 38},"msg": "注册成功","count": 1
}
登陆
{"code": 0,"data": {"id": 38,"username": "ht"},"msg": "登录成功","count": 1
}
投票
{"code": 0,"data": 22,"msg": "投票成功","count": 1
}
删除投票
{"code": 0,"data": null,"msg": "删除投票成功","count": 1
}
注销用户
{"code": 0,"data": null,"msg": "删除成功","count": 1
}
获取自己的投票记录
{"code": 0,"data": [{"id": 24,"user_id": 38,"player_id": 1,"add_time": 1729058838,"activity_id": 1},{"id": 23,"user_id": 38,"player_id": 2,"add_time": 1729058710,"activity_id": 1}],"msg": "获取投票列表成功","count": 1
}
修改密码
{"code": 0,"data": "新密码是:111111","msg": "修改密码成功","count": 1
}

参赛者

注册
{"code": 0,"data": {"id": 6,"nickname": "MJ","aid": 0,"ref": 0,"avatar": 0,"score": 0,"declaration": "","password": "111111"},"msg": "注册成功","count": 1
}
参与活动
{"code": 0,"data": null,"msg": "参加活动成功","count": 1
}
修改参赛宣言
{"code": 0,"data": "宣言更改为:原来你也玩原神,原神启动","msg": "宣言更改成功","count": 1
}
查看可参加的活动列表(GET)
{"code": 0,"data": [{"id": 1,"name": "run","state": 1},{"id": 2,"name": "climb","state": 1}],"msg": "获取成功","count": 1
}
退出正在参与的活动
{"code": 0,"data": "被扣除积分为:0","msg": "退出活动成功","count": 1
}
获得给自己投票的玩家列表
{"code": 0,"data": [{"id": 19,"user_id": 31,"player_id": 6,"add_time": 0,"activity_id": 1},{"id": 17,"user_id": 32,"player_id": 6,"add_time": 0,"activity_id": 1}],"msg": "获取投票列表成功","count": 1
}
获得在某个活动中给自己投票的玩家列表
{"code": 0,"data": [{"id": 19,"user_id": 31,"player_id": 6,"add_time": 0,"activity_id": 1},{"id": 17,"user_id": 32,"player_id": 6,"add_time": 0,"activity_id": 1}],"msg": "获取投票列表成功","count": 1
}
获得某项活动的排行榜(待重构)

想使用借鉴交易型结构,通过遍历数据库vote的条目来得出某项活动中各个参赛者的得分。

{"code": 0,"data": [{"PlayerID": 1,"Score": 3},{"PlayerID": 4,"Score": 2},{"PlayerID": 2,"Score": 1}],"msg": "获取成功","count": 1
}

管理员

注册
{"code": 0,"data": {"id": 0,"controller_name": "AweiRu","password": "111111"},"msg": "注册成功","count": 1
}
添加活动
{"code": 0,"data": {"id": 3,"name": "rush","state": 1},"msg": "注册成功","count": 1
}
获取参赛者总分列表
{"code": 0,"data": [{"id": 2,"nickname": "Yossi","aid": 1,"ref": 2,"avatar": 1122,"score": 124,"declaration": "我是吆西,日服球王","password": "111111"},{"id": 1,"nickname": "manba","aid": 1,"ref": 1,"avatar": 1112,"score": 100,"declaration": "我是牢大,点赞复活我","password": "111111"},{"id": 4,"nickname": "Zhyz","aid": 2,"ref": 4,"avatar": 3423,"score": 100,"declaration": "球队输了,我詹没输","password": "111111"},{"id": 5,"nickname": "iqun","aid": 1,"ref": 0,"avatar": 0,"score": 100,"declaration": "我爱玩原神,原神启动","password": "111111"},{"id": 6,"nickname": "MJ","aid": 1,"ref": 0,"avatar": 0,"score": 100,"declaration": "原来你也玩原神,原神启动","password": "111111"},{"id": 3,"nickname": "Cr7","aid": 0,"ref": 3,"avatar": 7777,"score": 99,"declaration": "我是罗,爱越位和偷金球","password": "111111"}],"msg": "获取成功","count": 1
}
更新某个参赛者总分
{"code": 0,"data": "Yossi更新之后的得分为:100","msg": "更新成功","count": 1
}
关闭某项活动
{"code": 0,"data": {"id": 1,"name": "run","state": 1},"msg": "关闭成功","count": 1
}
去除某个参赛者在某项活动中的得分
{"code": 0,"data": "删除了MJ在run活动的2票","msg": "删除成功","count": 1
}
去除某个用户对于某个活动的投票
{"code": 0,"data": "扣分的参赛者有:1,2","msg": "删除成功","count": 1
}

活动

获取所有活动列表
{"code": 0,"data": [{"id": 1,"name": "run","state": 0},{"id": 2,"name": "climb","state": 1},{"id": 3,"name": "rush","state": 1}],"msg": "获取成功","count": 1
}
获取参与某项活动的参赛者列表
{"code": 0,"data": [{"id": 1,"nickname": "manba","aid": 1,"ref": 1,"avatar": 1112,"score": 99,"declaration": "我是牢大,点赞复活我","password": "111111"},{"id": 2,"nickname": "Yossi","aid": 1,"ref": 2,"avatar": 1122,"score": 99,"declaration": "我是吆西,日服球王","password": "111111"},{"id": 5,"nickname": "iqun","aid": 1,"ref": 0,"avatar": 0,"score": 100,"declaration": "我爱玩原神,原神启动","password": "111111"},{"id": 6,"nickname": "MJ","aid": 1,"ref": 0,"avatar": 0,"score": 98,"declaration": "原来你也玩原神,原神启动","password": "111111"}],"msg": "获取成功","count": 1
}

设计感悟

  1. 对于获取数据的判空操作,获取数据时有以下常见两种形式:

    username := c.DefaultPostForm("username", "")
    playerIdStr := c.DefaultPostForm("player_id", "0")
    

    我们很容易看出,对于字符串类型的判空,在接收时只需要将defaultvalue这一位设置为空字符串就可以。然而,对于将要由字符串类型转为int型是数据,我们的defaultvalue要设置为0(int型的默认零值),这样可以统一对于获取数据的处理格式。

  2. 对于数据库的存储,数据更新,往往在model文件中的函数要给出error型的返回值,这样可以方便查看错误类型(如果数据库上的操作不成功,可以反馈到程序中)

  3. 在路由部分上方写上这个路由是干什么的,以及需要传入的参数名称及类型是一个很好的习惯,方便检验

  4. 有一些功能的设计思路还是比较巧妙的,比如用户的删除自己投票,管理员的删除某个用户对某项活动的投票,管理员是删除某个参赛者的某项活动的投票以及用户类的退出活动,这些项的设计还是值得一看的。

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

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

相关文章

创建包含可导入浏览器信任的SSL自签名证书

问题:现在的三大浏览器,chrome、edge、firefox 一般都默认启用https检查,这就要求我们自建的局域网内的网址和其他诸如nextcloud、photoprism、tiddlywiki等应用也必须要有证书。解决方法是使用openssl自己生成一个。由此则会再衍生出一个问题…

爬虫prc技术----小红书爬取解决xs

知识星球:知识星球 | 深度连接铁杆粉丝,运营高品质社群,知识变现的工具知识星球是创作者连接铁杆粉丝,实现知识变现的工具。任何从事创作或艺术的人,例如艺术家、工匠、教师、学术研究、科普等,只要能获得一…

vscode解决中文注释乱码,意料之外的原因

问题详情: c文件编码格式是:utf-8,vscode打开格式也是utf-8,但中文注释仍是乱码。可是用notepad打开中文显示却是正常 notepad显示编码如图: notepad打开文件: vscode显示编码如图: vscode打开…

Re75 读论文:Toolformer: Language Models Can Teach Themselves to Use Tools

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文全名:Toolformer: Language Models Can Teach Themselves to Use Tools 论文下载地址:https://arxiv.org/abs/2302.04761 这篇文章是介绍tool learning的,大概来说就是…

闪电麦昆 语音控制齿轮行进轨迹,ESP32搭配语音控制板,串口通信,附视频演示地址

演示地址 https://www.bilibili.com/video/BV1cW421d79L/?vd_sourceb8515e53f6d4c564b541d98dcc9df990 语音控制板的配置 web展示页面 esp32 程序 #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include <LittleFS.h> #include <WebSo…

Arthas常用的命令(三)--monitor、jad 、stack

monitor&#xff1a;监控方法的执行情况 监控指定类中方法的执行情况 用来监视一个时间段中指定方法的执行次数&#xff0c;成功次数&#xff0c;失败次数&#xff0c;耗时等这些信息 参数说明 方法拥有一个命名参数 [c:]&#xff0c;意思是统计周期&#xff08;cycle of ou…

安装TDengine数据库3.3版本和TDengine数据库可视化管理工具

安装TDengine数据库3.3版本和TDengine数据库可视化管理工具 一、下载安装包二、解压安装包三、部署四、启动服务五、进入数据库六、创建数据库、表和往表中插入数据七、测试 TDengine 性能八、使用数据库九、查询数据十、TDengine数据库可视化界面 一、下载安装包 TDengine-cl…

YOLO11改进 | 注意力机制 | 添加SE注意力机制

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 本文介绍了YOLOv11添加SE注意力机制&…

C语言 | 第十五章 | 指针函数 函数指针 内存分配 结构体

P 141 返回指针的函数 2023/2/16 一、基本介绍 C语言 允许函数的返回值是一个指针&#xff08;地址&#xff09;&#xff0c;这样的函数称为指针函数。 二、入门案例 案例&#xff1a;请编写一个函数 strlong()&#xff0c;返回两个字符串中较长的一个。 #include<stdi…

【windows】win10提示‘adb‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

问题日志 adb devices adb 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件 解决方案 下载adb&#xff0c;将adb放到如下目录 将 adb.exe AdbWinApi.dll AdbWinUsbApi.dll 文件放到以下目录 C:\Windows\SysWOW64 C:\Windows\System32 测试验证 adb An…

被DNS污染劫持,怎么见招拆招?

在畅游互联网的海洋时&#xff0c;我们可能会遭遇DNS污染劫持这一 “暗礁”&#xff0c;它就像一个隐藏在暗处的 “海盗”&#xff0c;干扰着我们正常的网络航行。那么&#xff0c;当遇到DNS污染劫持时&#xff0c;我们该如何见招拆招呢&#xff1f; 首先&#xff0c;我们要明…

JAVA面向对象的四大特征是什么?

目录 1. 封装&#xff08;Encapsulation&#xff09; 特点&#xff1a; 代码示例&#xff1a; 解释&#xff1a; 2. 继承&#xff08;Inheritance&#xff09; 特点&#xff1a; 代码示例&#xff1a; 解释&#xff1a; 3. 多态&#xff08;Polymorphism&#xff09; …

区块链技术与农产品溯源:实现透明供应链的关键

引言 随着食品安全问题和消费者对产品质量要求的提升&#xff0c;农产品溯源变得越来越重要。消费者希望知道他们购买的农产品从何而来&#xff0c;经历了哪些过程以及是否符合安全标准。区块链技术因其去中心化、不可篡改和透明的特点&#xff0c;成为实现农产品溯源的理想选…

如何解决与kernel32.dll相关的常见错误:详细指南解析kernel32.dll文件缺失、损坏或错误加载问题

当你的电脑中出现错误kernel32.dll丢失的问题&#xff0c;会导致电脑不能出现正常运行&#xff0c;希望能够有效的帮助你有效的将丢失的kernel32.dll文件进行修复同时也给大家介绍一些关于kernel32.dll文件的相关介绍&#xff0c;希望能够有效的帮助你快速修复错误。 kernel32.…

TensorFlow 的核心概念

TensorFlow 是一个开源的机器学习框架&#xff0c;由 Google 开发和维护。它提供了一个强大的工具集&#xff0c;用于构建和训练各种机器学习模型。 TensorFlow 的核心概念是计算图&#xff08;Computational Graph&#xff09;。计算图由节点&#xff08;Nodes&#xff09;和…

QT 鼠标和键盘事件

在Qt中&#xff0c;可以使用事件处理机制来监听和处理鼠标事件和键盘事件。具体来说&#xff0c;重载事件处理函数或者使用事件过滤器是最常见的方法。以下是一些常用的事件处理函数以及如何监听鼠标事件和键盘事件的示例。 1. 处理鼠标事件 要处理鼠标事件&#xff0c;可以重…

ES6基础知识

一、定义变量的关键字let和const 1. let 定义变量的语法&#xff1a; let 变量名 值; 2. 和var定义变量的区别 1. 是否支持同一个作用域变量同名 var支持&#xff0c;let不支持 2. 是否支持预解析 var支持&#xff0c;let不支持 3. 是否会挂载在window对象…

Unity RPG梦幻场景素材(附下载链接)

Unity RPG梦幻场景素材 点击下载资源 效果图&#xff1a; 资源链接

OpeneBayes 教程上新 | 打败 GPT-4V?超强开源多模态大模型 LLaVA-OneVision 正式上线!

大语言模型&#xff08;Large Language Model&#xff0c;简称 LLM&#xff09;与多模态大模型&#xff08;Large Multimodal Model&#xff0c;简称 LMM&#xff09;是人工智能领域的两个核心发展方向。 LLM 主要致力于处理和生成文本数据&#xff0c;而 LMM 则更进一步&#…

Git-本地项目同步到远程仓库

一、Git初始化项目 git initgit init 是 Git 中用于初始化一个新仓库的命令&#xff0c;通常用来在现有目录中创建一个 Git 仓库或重新初始化一个现有的 Git 仓库。通过 git init&#xff0c;你可以将一个普通的目录转变为 Git 受控的项目目录。 在当前目录中初始化一个新的 …