gin+gorm增删改查目录框架
从网上找资料,发现,很多都是直接的结构
路由,后端的controller层,还有model层,都是放在了同一个main.go文件中,如果写项目的话,还得自己去拆文件,拆代码,经过查询和自己总结,下面放一个目录框架
总体目录结构

按照业务流程顺序,解释说明
1、加载自定义封装函数文件、数据库、redis
package mainimport ("ginchat/router""ginchat/utils"
)func main() {utils.InitConfig()utils.InitMysql()utils.InitRedis()r := router.Router()r.Run(":8081")
}
依次的三个函数
system_init.go文件里面
package utilsimport ("fmt""github.com/go-redis/redis/v8""github.com/spf13/viper""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger""log""os""time"
)var (DB *gorm.DBerr errorRed *redis.Client
)func InitRedis() {fmt.Print("随便打印点什么,标记一下")Red = redis.NewClient(&redis.Options{Addr: viper.GetString("redis.addr"),Password: viper.GetString("redis.password"),DB: viper.GetInt("redis.DB"),PoolSize: viper.GetInt("redis.poolSize"),MinIdleConns: viper.GetInt("redis.minIdleConn"),})}func InitConfig() {viper.SetConfigName("app")viper.AddConfigPath("config")err := viper.ReadInConfig()if err != nil {fmt.Println(err)}fmt.Println("config app", viper.Get("app"))fmt.Println("config mysql", viper.Get("mysql"))
}func InitMysql() {newLogger := logger.New(//自定义日志模版 打印SQL语句log.New(os.Stdout, "\r\n", log.LstdFlags),logger.Config{SlowThreshold: time.Second, //慢SQL阈值LogLevel: logger.Info, //级别Colorful: true, //彩色},)fmt.Print(newLogger)DB, err = gorm.Open(mysql.Open(viper.GetString("mysql.dns")), &gorm.Config{})if err != nil {fmt.Println("连接数据库失败", err)} else {fmt.Printf("数据库连接成功: %v", DB)}}
2、加载路由文件
package routerimport ("fmt""ginchat/service""github.com/gin-gonic/gin"
)func Router() *gin.Engine {fmt.Print("进入路由了")r := gin.Default()//用户模块r.GET("/user/getUserList", service.GetUserList)r.POST("/user/createUser", service.CreateUser)r.DELETE("/user/deleteUser", service.DeleteUser)r.PUT("/user/updateUser", service.UpdateUser)return r
}
3、这里面的MySQL和Redis配置,可以直接写死在这个文件里面,也可以单独摘出来,放在配置文件中,这里是放在了配置文件中
app.yml中
mysql:dns: admin3:123456@tcp(127.0.0.1:3306)/ginchat?charset=utf8mb4&parseTime=True&loc=Local
redis:addr:"127.0.0.1:6379"password:""DB:0poolSize:30minIdleConn:30
说明一下,dns里面的参数
账号:密码@tcp(ip:端口号)/数据库名字?xxxxxxxx
4、然后,预备的工作就完成了。另外,有一个sql文件下面的testGorm.go文件
package mainimport ("fmt""ginchat/models""gorm.io/driver/mysql""gorm.io/gorm"
)func main() {db, err := gorm.Open(mysql.Open("admin3:123456@tcp(127.0.0.1:3306)/ginchat?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{})if err != nil {fmt.Println("连接数据库失败", err)} else {fmt.Printf("数据库连接成功: %v", db)}err2 := db.AutoMigrate(&models.UserBasic{})if err2 != nil {return} else {fmt.Printf("创建表成功: %v", db)}
}
用于临时生成数据表的一个文件,可以去直接执行此函数,生成数据表,或者也可以自己手动去利用navicat去创建表格
这里用到了models包下面的UserBasic{}
package modelsimport ("fmt""ginchat/utils""gorm.io/gorm"
)type UserBasic struct {gorm.ModelName stringPassword stringPhone string `valid:"matches(^1[3-9]{1}\\d{9}$)"`Email string `valid:"email"`Avatar string //头像Identity stringClientIp stringSalt stringClientPort stringLoginTime uint64HeartbeatTime uint64LoginOutTime uint64IsLogout boolDeviceInfo string
}func (table *UserBasic) TableName() string {return "user_basic"
}func GetUserList() []*UserBasic {data := make([]*UserBasic, 10)//fmt.Printf("data的内容为: %v\n", &data)utils.DB.Find(&data)for _, v := range data {fmt.Println(v)}return data}func CreateUser(user UserBasic) *gorm.DB {return utils.DB.Create(&user)
}func DeleteUser(user UserBasic) *gorm.DB {return utils.DB.Delete(&user)
}func UpdateUser(user UserBasic) *gorm.DB {return utils.DB.Model(&user).Updates(UserBasic{Name: user.Name, Phone: user.Phone, Email: user.Email, Password: user.Password, Avatar: user.Avatar})
}func FindUserByName(name string) UserBasic {user := UserBasic{}utils.DB.Where("name=?", name).First(&user)return user
}func FindUserByPhone(phone string) UserBasic {user := UserBasic{}utils.DB.Where("phone=?", phone).First(&user)return user
}func FindUserByEmail(email string) UserBasic {user := UserBasic{}utils.DB.Where("email=?", email).First(&user)return user
}
UserBasic里面需要定义好数据表的字段
5、gorm.Model是gorm包已经先给预先设置好的4个字段

同时,前面是用驼峰式写法,如果不做特殊说明的话,基本上就会转变为下划线方式去设置字段,这个是gorm默认的对应关系
字段名可以控制,字段类型和大小,如果在创建之后不符合自己要求,可以自己额外修改
6、接下来就是后面的调取引用函数了
controller层
package serviceimport ("fmt""ginchat/models""ginchat/utils""github.com/asaskevich/govalidator""github.com/gin-gonic/gin""math/rand""strconv"
)func GetUserList(c *gin.Context) {data := make([]*models.UserBasic, 10)data = models.GetUserList()c.JSON(200, gin.H{"code": 200,"message": data,})
}func CreateUser(c *gin.Context) {user := models.UserBasic{}user.Name = c.PostForm("name")user.Phone = c.PostForm("phone")user.Email = c.PostForm("email")password := c.PostForm("password")rePassword := c.PostForm("repassword")salt := fmt.Sprintf("%06d", rand.Int31())if password != rePassword {c.JSON(200, gin.H{"code": -1,"message": "两次密码不一样!",})return}data1 := models.FindUserByName(user.Name)fmt.Print(data1)if data1.Name != "" {c.JSON(200, gin.H{"code": -1,"message": "用户名不能重复!",})return}data2 := models.FindUserByPhone(user.Phone)fmt.Print(data2)if data2.Phone != "" {c.JSON(200, gin.H{"code": -1,"message": "手机号不能重复!",})return}data3 := models.FindUserByEmail(user.Email)fmt.Print(data3)if data3.Email != "" {c.JSON(200, gin.H{"code": -1,"message": "邮箱不能重复!",})return}user.Password = utils.MakePassword(password, salt)user.Salt = saltmodels.CreateUser(user)c.JSON(200, gin.H{"code": 0,"message": "新增用户成功!",})}func DeleteUser(c *gin.Context) {user := models.UserBasic{}id, _ := strconv.Atoi(c.Query("id"))user.ID = uint(id)models.DeleteUser(user)c.JSON(200, gin.H{"code": 0,"message": "删除用户成功!",})
}func UpdateUser(c *gin.Context) {user := models.UserBasic{}id, _ := strconv.Atoi(c.PostForm("id"))user.ID = uint(id)user.Name = c.PostForm("name")user.Password = c.PostForm("password")user.Phone = c.PostForm("phone")user.Email = c.PostForm("email")_, err := govalidator.ValidateStruct(user)if err != nil {fmt.Print(err)c.JSON(200, gin.H{"code": -1,"message": "修改参数不匹配!",})return} else {fmt.Print(user)models.UpdateUser(user)c.JSON(200, gin.H{"code": 0,"message": "修改用户成功!",})}}
这里举例的是,用户信息表的相关增删改查
另外两个自己封装函数文件,暂时上面几个函数未用到
先贴在这里md5.go和resp.go
package utilsimport ("crypto/md5""encoding/hex""strings"
)// Md5Encode 小写
func Md5Encode(data string) string {h := md5.New()h.Write([]byte(data))tempStr := h.Sum(nil)return hex.EncodeToString(tempStr)
}// MD5Encode 大写
func MD5Encode(data string) string {return strings.ToUpper(Md5Encode(data))
}// MakePassword 加密
func MakePassword(plainpwd, salt string) string {return Md5Encode(plainpwd + salt)
}// ValidPassword 解密
func ValidPassword(plainpwd, salt, password string) bool {return Md5Encode(plainpwd+salt) == password
}
package utilsimport ("encoding/json""net/http"
)type H struct {Code intMsg stringData interface{}Rows interface{}Total interface{}
}func Resp(w http.ResponseWriter, code int, data interface{}, msg string) {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusOK)h := H{Code: code,Data: data,Msg: msg,}ret, err := json.Marshal(h)if err != nil {panic(err)}w.Write(ret)
}func RespFail(w http.ResponseWriter, msg string) {Resp(w, -1, nil, msg)
}func RespOK(w http.ResponseWriter, data interface{}, msg string) {Resp(w, 0, data, msg)
}func RespOKList(w http.ResponseWriter, data interface{}, total interface{}) {RespList(w, 0, data, total)
}func RespList(w http.ResponseWriter, code int, data interface{}, total interface{}) {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusOK)h := H{Code: code,Rows: data,Total: total,}ret, err := json.Marshal(h)if err != nil {panic(err)}w.Write(ret)
}
此部分代码是看了B站up主之后总结出来的,感兴趣的可以去搜索看一下
000_项目背景能获得什么技术栈_哔哩哔哩_bilibili
相关文章:
gin+gorm增删改查目录框架
从网上找资料,发现,很多都是直接的结构 路由,后端的controller层,还有model层,都是放在了同一个main.go文件中,如果写项目的话,还得自己去拆文件,拆代码,经过查询和自己总结,下面放…...
python进阶(二)导入import 机制 | 导入import 用法 工作原理全解析
文章目录 1. 整体概念基本介绍1.1 包package1.2 模块 module 2 基本语法2.1 import直接使用2.2 from 及其用法3.1 as的用法 3 工作原理3.1 搜寻3.2 执行3.3 避免导入模块代码执行 参考《Python应该如何导入(import)模块及包》梳理 1. 整体概念基本介绍 …...
极客时间-《罗剑锋的 C++ 实战笔记》文章笔记 + 个人思考
极客时间-《罗剑锋的 C 实战笔记》文章笔记 个人思考 语言特性06 | auto/decltype:为什么要有自动类型推导? 语言特性 06 | auto/decltype:为什么要有自动类型推导? auto 在C 11 引入。 为什么说C是静态强类型语言?…...
Pytorch 对比TensorFlow 学习:Day 17-18: 循环神经网络(RNN)和LSTM
Day 17-18: 循环神经网络(RNN)和LSTM 在这两天的学习中,我专注于理解循环神经网络(RNN)和长短期记忆网络(LSTM)的基本概念,并学习了它们在处理序列数据时的应用。 1.RNN和LSTM基础…...
Java基础 - 07 Set之Set,AbstractSet
上边几篇,我们对java的List集合进行相关介绍,了解了关于List集合下的相关实现类的方法或者接口。 自本篇开始,将围绕java的Set进行介绍,也是对我java知识的巩固吧,处理业务越多,发现自己对基础知识的薄弱&…...
C++17新特性(三)新的标准库组件
1. optional 在编程时,我们经常会遇到可能会返回/传递/使用一个确定类型对象的场景。也就是说,这个对象可能有一个确定类型的值也可能没有任何值。因此,我们需要一种方法来模拟类似指针的语义:通过nullptr表示指针为空。解决方法…...
Spring Boot入门
SpringBoot介绍 什么是SpringBoot Spring Boot是由Pivotal团队提供的全新框架,其中“Boot”的意思就是“引导”,Spring Boot 并不是对 Spring 功能上的增强,而是提供了一种快速开发 Spring应用的方式。 特点 • 嵌入的 Tomcat,…...
【LeetCode】数学精选4题
目录 1. 二进制求和(简单) 2. 两数相加(中等) 3. 两数相除(中等) 4. 字符串相乘(中等) 1. 二进制求和(简单) 从字符串的右端出发向左做加法,…...
【漏洞复现】Hikvision SPON IP网络对讲广播系统命令执行漏洞(CVE-2023-6895)
文章目录 前言声明一、系统简介二、漏洞描述三、影响版本四、漏洞复现五、修复建议 前言 Hikvision Intercom Broadcasting System是中国海康威视(Hikvision)公司的一个对讲广播系统。 声明 请勿利用文章内的相关技术从事非法测试,由于传播…...
IDEA在重启springboot项目时没有自动重新build
IDEA在重启springboot项目时没有自动重新build 问题描述 当项目里面某些依赖或者插件更新了,target的class文件没有找到,导致不是我们需要的效果。 只能手动的清理target文件,麻烦得很 , 单体项目还好说,一次清理就…...
华为设备NAT的配置
实现内网外网地址转换 静态转换 AR1: sys int g0/0/0 ip add 192.168.10.254 24 int g0/0/1 ip add 22.33.44.55 24 //静态转换 nat static global 22.33.44.56 inside 192.168.10.1 动态转换 最多有两台主机同时访问外网 AR1: sys int g0/0/0 ip add…...
48-DOM节点,innerHTML,innerText,outerHTML,outerText,静态获取,单机click,cssText
1.DOM基础 Document Object Module,文档对象模型,window对象,document文档,都可以获取和操作 1)文档节点 2)属性节点(标签内的属性href,src) 3)文本节点(标签内的文字) 4)注释节点 5)元素节点(标签) 2.获取元素节点 2.1通过标签名获取getElementsByTagName() …...
多输入多输出 | Matlab实现基于LightGBM多输入多输出预测
多输入多输出 | Matlab实现基于LightGBM多输入多输出预测 目录 多输入多输出 | Matlab实现基于LightGBM多输入多输出预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现基于LightGBM多输入多输出预测(完整源码和数据) 1.data为数据集&a…...
【欢迎您的到来】这里是开源库get_local_info作者的付费专栏
您好, 我是带剑书生,开源库get_local_info的作者,欢迎您的到来,这里是我的付费专栏,在上一个付费专栏里,用简洁的语言,通俗的话语,帮助您更好的学习了Rust,现在将用本专栏…...
Java SE入门及基础(23)
目录 方法带参 1. 构造方法带参 案例场景 思考:以上代码存在什么问题? 2. 方法带参 方法带参语法 案例场景 思考:以上代码存在什么问题? Java SE文章参考:Java SE入门及基础知识合集-CSDN博客 方法带参 1. 构造方法带参 …...
蓝桥杯回文日期判断
思想:对于回文数的判断方法,最快的就是取其中一半的字符串长度,为s,然后将其进行翻转为s’ ,再把两者进行拼接即可保证是回文数,这样子就解决了枚举所有回文数的问题。 注意点: 要求必须是有效…...
Qt文件和目录相关操作
1.相关说明 QCoreApplication类、QFile类、QDir、QTemporaryDir类、QTemporaryFile类、QFileSystemWatcher类的相关函数 2.相关界面 3.相关代码 #include "dialog.h" #include "ui_dialog.h" #include <QFileDialog> #include <QTemporaryDir>…...
递归、搜索与回溯算法(专题一:递归)
往期文章(希望小伙伴们在看这篇文章之前,看一下往期文章) (1)递归、搜索与回溯算法(专题零:解释回溯算法中涉及到的名词)【回溯算法入门必看】-CSDN博客 接下来我会用几道题&#…...
element-ui 打包流程源码解析(下)
目录 目录结构和使用1,npm 安装1.1,完整引入1.2,按需引入 2,CDN3,国际化 接上文:element-ui 打包流程源码解析(上) 文章中提到的【上文】都指它 ↑ 目录结构和使用 我们从使用方式来…...
ChatGPT给出的前端面试考点(Vue.js)
ChatGPT给出的前端面试考点(Vue.js) 答案 1. Vue.js是什么?它的主要特点是什么? Vue.js是一个渐进式JavaScript框架,用于构建用户界面。它的主要特点包括: 数据绑定:Vue.js使用双向数据绑定&…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
