Gin,Gorm实现Web计算器
目录
- 仓库链接
- 0.PSP表格
- 1. 成品展示
- 1.基础运算
- 2. 清零回退
- 3.错误提示
- 4.历史记录
- 拓展功能
- 1.前端可修改的利率计算器
- 2.科学计算器
- 3. 按钮切换不同计算器模式
- 4.用户在一次运算后不清零继续输入操作符,替换表达式为上次答案
- 2.设计实现过程
- 3.代码说明
- 4.心路历程和收获
仓库链接
2301-计算机学院-软件工程 | https://bbs.csdn.net/forums/ssynkqtd-05 |
---|---|
这个作业要求在哪里 | https://bbs.csdn.net/topics/617377308 |
这个作业的目标 | 实现一个前后端分离计算器 |
其他参考文献 | … |
backend
frontend
Google 开源项目风格指南——中文版
Google Style Guides
0.PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 40 | 20 |
• Estimate | 估计这个任务需要多少时间 | 10 | 10 |
Development | 开发 | 650 | 630 |
• Analysis | 需求分析 (包括学习新技术) | 40 | 30 |
• Design Spec | 生成设计文档 | 80 | 75 |
• Design Review | 设计复审 | 35 | 45 |
• Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 25 | 20 |
• Design | 具体设计 | 35 | 30 |
• Coding | 具体编码 | 325 | 320 |
• Code Review | 代码复审 | 65 | 60 |
• Test | 测试(自我测试,修改代码,提交修改) | 60 | 50 |
Reporting | 报告 | 95 | 90 |
• Test Report | 测试报告 | 25 | 20 |
• Size Measurement | 计算工作量 | 10 | 15 |
• Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 45 | 55 |
合计 | 670 | 630 |
1. 成品展示
1.基础运算
2. 清零回退
3.错误提示
4.历史记录
拓展功能
1.前端可修改的利率计算器
2.科学计算器
3. 按钮切换不同计算器模式
4.用户在一次运算后不清零继续输入操作符,替换表达式为上次答案
2.设计实现过程
- 前端:前端需要在上一轮作业的基础上加以完善。首先要扩充为两个输入框,一个用于显示用户输入的表达式,一个用于显示答案。同时在上一轮的form基础上再做一个利率计算器(利率计算器和存款计算器可以共用一个div)。同时使用fetch向后端传发数据。
- 后端:后端使用Gin做Web框架。通过路由组和hander接前端请求。Gin相比于Hertz是一个轻量级的框架适合做这种小项目。数据库交互用Gorm。
- 数据库:只用到了Mysql。存历史记录,存款、贷款三张表。暂且把这个计算器看作单机版本,所以在存历史记录的时候没有特意区分不同用户ID。可视化工具推荐Dbeaver。
3.代码说明
- 前端采用fetch通信。fetch的语法很简明,不再赘述。以查询历史记录为例:
function ans() {fetch("http://localhost:8080/history/", {method: 'GET',headers: {'Content-Type': 'application/json'},}).then(response => response.json()).then(data => {// 处理后端的响应if (data.code === 200) {const expVal = data.result;if (expVal.length > 0) {const displayText = expVal.map((item, index) => `<div class="expression-container" id="expression-${index}">$ ${item.Exp} = ${item.Val} $</div>`).join('<br>');Swal.fire({title: '历史记录(近 10 条)',html: displayText,icon: 'success',confirmButtonText: '关闭'});// 使用MathJax渲染数学表达式for (let i = 0; i < expVal.length; i++) {MathJax.Hub.Queue(["Typeset", MathJax.Hub, `expression-${i}`]);}} else {// 如果没有之前的数据,显示提示消息Swal.fire('没有可显示的数据', '', 'error');}} else {// code 不为 200,给出提示console.error(`响应状态不是 200,错误消息:${data.msg}`);}}).catch(error => {console.error("An error occurred while receiving the result from the backend: " + error);});
}
页面的切换用一个变量来控制,相当于一个mod 3 的加法,控制div的可见性。
function mode() {st = (st + 1) % 3;const normalCalculator = document.querySelector('.normal');const interestCalculator = document.querySelector('.interest');let bt = document.getElementById("topMode");var updateInter = document.getElementById("update_inter");var updateInter2 = document.getElementById("update_inter2");if (st === 0) {normalCalculator.style.display = 'block';interestCalculator.style.display = 'none';bt.innerHTML = "科学计算器"} else if (st === 1) {normalCalculator.style.display = 'none';interestCalculator.style.display = 'block';updateInter.style.display = "block";updateInter2.style.display = "none";bt.innerHTML = "存款计算器"} else if (st === 2) {normalCalculator.style.display = 'none';interestCalculator.style.display = 'block';updateInter2.style.display = "block";updateInter.style.display = "none";bt.innerHTML = "贷款计算器"}
}
- 后端启动服务:
package mainimport ("WebCalculator/dal/mysql""WebCalculator/router""github.com/gin-contrib/cors""github.com/gin-gonic/gin"
)func main() {mysql.Init()r := gin.Default()// 解决跨域问题r.Use(cors.Default())router.SetUpRoutes(r)err := r.Run(":8080")if err != nil {panic(err)}
}
注意需要解决跨域问题。查阅资料得知最近的Gin官方已经给出了对于跨域的问题的默认配置无需再手动配置,一行代码就可以了。同时在main函数中初始化mysql相关链接信息和路由组。
func SetUpRoutes(engine *gin.Engine) {home := engine.Group("/"){home.GET("/hello", hello.Hello)}his := engine.Group("/history"){his.POST("/", history.AddHistory)his.GET("/", history.QueryHistory)}dep := engine.Group("/deposit"){dep.POST("/", deposit.UpdateDep)dep.GET("/", deposit.QueryInterest)}l := engine.Group("/loans"){l.GET("/", loans.QueryInterest)l.POST("/", loans.UpdateLoans)}
}
hander包编写具体实现方法。
以查询利息为例:
func QueryInterest(c *gin.Context) {// 获取查询参数principalStr := c.DefaultQuery("principal", "")durationStr := c.DefaultQuery("duration", "")// 将字符串转换为浮点数principal, err1 := strconv.ParseFloat(principalStr, 64)duration, err2 := strconv.ParseFloat(durationStr, 64)if err1 != nil || err2 != nil {// 处理转换错误,例如返回错误响应c.JSON(http.StatusOK, gin.H{"code": 400,"msg": "输入无效",})return}interest := service.CalInterest(entity.MoneyCal{Money: principal,Duration: duration,}, 1)c.JSON(http.StatusOK, gin.H{"code": 200,"msg": "计算成功","result": interest,})}
注意存款和贷款的逻辑几乎相同。所以可以增加一个传入参数op,0/1表示不同类型就可以复用计算函数。
func ExistDuration(duration float64, op int) bool {if op == 1 {result := mysql.DB.Where("duration = ?", duration).First(&entity.Deposit{})return result.Error != gorm.ErrRecordNotFound}result := mysql.DB.Where("duration = ?", duration).First(&entity.Loan{})return result.Error != gorm.ErrRecordNotFound
}func CalInterest(cal entity.MoneyCal, op int) float64 {duration := cal.Durationmoney := cal.Moneyif op == 1 {var deposit entity.Depositmysql.DB.Where("duration <= ?", duration).Order("duration desc").Limit(1).First(&deposit)return money * deposit.Rate / 100}var loans entity.Loanmysql.DB.Where("duration <= ?", duration).Order("duration desc").Limit(1).First(&loans)return money * loans. Rate / 100
}
3.数据库
Gorm的数据库操作十分便利。提供了AutoMigrate来自动迁移表结构。有结构体的情况下可以自动建对应表.无需编写sql。
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{SkipDefaultTransaction: true,PrepareStmt: true,Logger: logger.Default.LogMode(logger.Info),})if err != nil {panic(err)}err = DB.AutoMigrate(&entity.History{}, &entity.Deposit{}, &entity.Loan{})if err != nil {return}
且gorm.Model包含许多实用信息,ID,CT,UPT等等。
4.心路历程和收获
后端部分其实没啥技术含量,主要是CRUD…
感觉最难的部分还是在前端,因为之前不会,所以几乎是一直在对着已有的HTML和CSS代码不断增删猜测效果/询问他人。感觉前端代码实在写的不堪入目,还好最后效果感觉还行。
有些疑惑为什么要一个人完成前后端,可能全栈是学院派的宿命。
相关文章:

Gin,Gorm实现Web计算器
目录 仓库链接0.PSP表格1. 成品展示1.基础运算2. 清零回退3.错误提示4.历史记录拓展功能1.前端可修改的利率计算器2.科学计算器3. 按钮切换不同计算器模式4.用户在一次运算后不清零继续输入操作符,替换表达式为上次答案 2.设计实现过程3.代码说明4.心路历程和收获 仓…...

11-网络篇-DNS步骤
1.URL URL就是我们常说的网址 https://www.baidu.com/?from1086k https是协议 m.baidu.com是服务器域名 ?from1086k是路径 2.域名 比如https://www.baidu.com 顶级域名.com 二级域名baidu 三级域名www 3.域名解析DNS DNS就是将域名转换成IP的过程 根域名服务器:…...

设计师都应该知道的事:极简主义家具该怎么去用
这座房子有黑暗而沉重的特征,包括棕色和白色的马赛克浴室瓷砖,弯曲的锻铁壁灯和土黄色的威尼斯石膏墙。但由于房屋与他们的风格相去甚远,白色,干净和简约,接下来我们就着这个方向去帮助房主进行改造。 她解释说&#x…...

设计模式02———建造者模式 c#
首先我们打开一个项目 在这个初始界面我们需要做一些准备工作 建基础通用包 创建一个Plane 重置后 缩放100倍 加一个颜色 更换天空盒(个人喜好) 任务:使用【UI】点击生成6种车零件组装不同类型车 【建造者模式】 首先资源商店下载车模型 将C…...

2023最新接口自动化测试面试题
1、get和post的区别? l http是上层请求协议,主要定义了服务端和客户端的交互规格,底层都是tcp/ip协议 l Get会把参数附在url之后,用?分割,&连接不同参数,Get获取资源,post会把…...

GaN器件的工作原理
目录 AlGaN/GaNHEMT 器件工作原理(常开-耗尽型器件)常关 AlGaN/GaN 功率晶体管(增强型器件)HD-GIT与SP-HEMT AlGaN/GaNHEMT 器件工作原理(常开-耗尽型器件) 来源:毫米波GaN基功率器件及MMIC电路…...

点云从入门到精通技术详解100篇-海量三维点云的空间索引及可视化应用(续)
目录 3.2.3 方向八叉树与八叉树的比较 3.3 多级索引结构 3.3.1 多级索引结构的构建...

androidx和v4包资源冲突解决方法
一、资源包会报如下错误: 错误类似 (androidx.core:core:1.10.0) 和 (com.android.support:support-compat:24.2.0) 表示资源重复,不知调用androidx包下面的,还是v4包下面的 Duplicate class android.support.v4.app.INotificationSideCha…...

【发烧期间随笔】第一次游戏开发经历的总结与反思
一、前言 这两天三阳了,头疼头晕恶心发烧打喷嚏流鼻涕咳嗽嗓子疼气管疼都找上门来了,这导致一周以来都没学什么东西,无意间又刷到各个游戏厂关于本人目标岗位HC骤减且要求造火箭的能力的消息,这两天一直是在病痛和焦虑中度过的&a…...

CCombBox组合框
1、 MFC_Combo_Box(组合框)的详细用法_mfc combo-CSDN博客 2、 常用属性设置: 属性 含义 data 设置内容,不同内容间用英文的分号“;”分隔 type 显示风格 Sort True 内容自动排序 常用接口: 接口 功能 CComboBox::AddString 组…...

机器学习-有监督学习-神经网络
目录 线性模型分类与回归感知机模型激活函数维度诅咒过拟合和欠拟合正则数据增强数值稳定性神经网络大家族CNNRNNGNN(图神经网络)GAN 线性模型 向量版本 y ⟨ w , x ⟩ b y \langle w, x \rangle b y⟨w,x⟩b 分类与回归 懂得两者区别激活函数&a…...

React之组件通信
#一、是什么 我们将组件间通信可以拆分为两个词: 组件通信 回顾Vue系列 (opens new window)的文章,组件是vue中最强大的功能之一,同样组件化是React的核心思想 相比vue,React的组件更加灵活和多样,按照不同的方式可…...

什么是微服务架构
阅读“微服务架构”一词可能会让您直观地了解该术语的含义:计算架构中的小型服务。这个定义并不完全错误,但也不完全正确。 微服务架构通常被称为“打破整体”的一种方式。遗憾的是,这与《2001:太空漫游》无关,而是将…...

<%=%>模板写法
<%%> 这种写法通常称为 "内嵌式模板" 或 "模板标记",在前端开发中,这种标记语法用于将动态数据嵌入HTML模板中。这种写法通常与模板引擎一起使用,这些模板引擎会根据提供的数据动态生成HTML。 不同的模板引擎可能…...

python爬取boss直聘数据(selenium+xpath)
文章目录 一、主要目标二、开发环境三、selenium安装和驱动下载四、主要思路五、代码展示和说明1、导入相关库2、启动浏览器3、搜索框定位创建csv文件招聘页面数据解析(XPATH)总代码效果展示 六、总结 一、主要目标 以boss直聘为目标网站,主要目的是爬取下图中的所…...

GEO生信数据挖掘(六)实践案例——四分类结核病基因数据预处理分析
前面五节,我们使用阿尔兹海默症数据做了一个数据预处理案例,包括如下内容: GEO生信数据挖掘(一)数据集下载和初步观察 GEO生信数据挖掘(二)下载基因芯片平台文件及注释 GEO生信数据挖掘&…...

8.Mobilenetv2网络代码实现
代码如下: import math import os import numpy as npimport torch import torch.nn as nn import torch.utils.model_zoo as model_zoo#1.建立带有bn的卷积网络 def conv_bn(inp, oup, stride):return nn.Sequential(nn.Conv2d(inp,oup,3,stride,biasFalse),nn.Bat…...

Spring Boot Controller
刚入门小白,详细请看这篇SpringBoot各种Controller写法_springboot controller-CSDN博客 Spring Boot 提供了Controller和RestController两种注解。 Controller 返回一个string,其内容就是指向的html文件名称。 Controller public class HelloControll…...

在网络安全、爬虫和HTTP协议中的重要性和应用
1. Socks5代理:保障多协议安全传输 Socks5代理是一种功能强大的代理协议,支持多种网络协议,包括HTTP、HTTPS和FTP。相比之下,Socks5代理提供了更高的安全性和功能性,包括: 多协议支持: Socks5代…...

Web测试框架SeleniumBase
首先,SeleniumBase支持 pip安装: > pip install seleniumbase它依赖的库比较多,包括pytest、nose这些第三方单元测试框架,是为更方便的运行测试用例,因为这两个测试框架是支持unittest测试用例的执行的。 Seleniu…...

jvm打破砂锅问到底- 为什么要标记或记录跨代引用
为什么要标记或记录跨代引用. ygc时, 直接把老年代引用的新生代对象(可能是对象区域)记录下来当做根, 这其实就是依据第二假说和第三假说, 强者恒强, 跨代引用少(存在互相引用关系的两个对象,是应该倾 向于同时生存或者同时消亡的). 拿ygc老年代跨代引用对象当做根…...

小程序长期订阅
准备工作 ::: tip 管理后台配置 小程序类目:住建(硬性要求) 功能-》订阅消息-》我的模版 申请模版:1、预约进度通知 2、申请结果通知 3、业务办理进度提醒 ::: 用户订阅一次后,可长期下发多条消息。目前长期性订阅…...

Studio One6.5中文版本版下载及功能介绍
Studio One是一款专业的音乐制作软件,由美国PreSonus公司开发。该软件提供了全面的音频编辑和混音功能,包括录制、编曲、合成、采样等多种工具,可用于制作各种类型的音乐,如流行音乐、电子音乐、摇滚乐等。 Studio One的主要特点…...

07-Zookeeper分布式一致性协议ZAB源码剖析
上一篇:06-Zookeeper选举Leader源码剖析 整个Zookeeper就是一个多节点分布式一致性算法的实现,底层采用的实现协议是ZAB。 1. ZAB协议介绍 ZAB 协议全称:Zookeeper Atomic Broadcast(Zookeeper 原子广播协议)。 Zook…...

云原生安全应用场景有哪些?
当今数字化时代,数据已经成为企业最宝贵的资产之一,而云计算作为企业数字化转型的关键技术,其安全性也日益受到重视。随着云计算技术的快速发展,云原生安全应用场景也越来越广泛,下面本文将从云原生安全应用场景出发&a…...

Step 1 搭建一个简单的渲染框架
Step 1 搭建一个简单的渲染框架 万事开头难。从萌生到自己到处看源码手抄一个mini engine出来的想法,到真正敲键盘去抄,转眼过去了很久的时间。这次大概的确是抱着认真的想法,打开VS从零开始抄代码。不知道能坚持多久呢。。。 本次的主题是搭…...

Excel 插入和提取超链接
构造超链接 HYPERLINK(D1,C1)提取超链接 Sheet页→右键→查看代码Sub link()Dim hl As HyperlinkFor Each hl In ActiveSheet.Hyperlinkshl.Range.Offset(0, 1).Value hl.AddressNext End Sub工具栏→运行→运行子过程→提取所有超链接地址参考: https://blog.cs…...

基础架构开发-操作系统、编译器、云原生、嵌入式、ic
基础架构开发-操作系统、编译器、云原生、嵌入式、ic 操作系统编译器词法分析AST语法树生成语法优化生成机器码 云原生容器开发一般遇到的岗位描述RDMA、DPDK是什么东西NFV和VNF是什么RisingWave云原生存储引擎开发实践 单片机、嵌入式雷达路线规划 ic开发 操作系统 以C和Rust…...

C++-Mongoose(3)-http-server-https-restful
1.url 结构 2.http和 http-restful区别在于对于mg_tls_opts的赋值 2.1 http和https 区分 a) port地址 static const char *s_http_addr "http://0.0.0.0:8000"; // HTTP port static const char *s_https_addr "https://0.0.0.0:8443"; // HTTP…...

git多分支、git远程仓库、ssh方式连接远程仓库、协同开发(避免冲突)、解决协同冲突(多人在同一分支开发、 合并分支)
1 git多分支 2 git远程仓库 2.1 普通开发者,使用流程 3 ssh方式连接远程仓库 4 协同开发 4.1 避免冲突 4.2 协同开发 5 解决协同冲突 5.1 多人在同一分支开发 5.2 合并分支 1 git多分支 ## 命令操作分支-1 创建分支git branch dev-2 查看分支git branch-3 分支合…...