gin+gorm增删改查目录框架

news2025/1/11 14:51:13

从网上找资料,发现,很多都是直接的结构

路由,后端的controller层,还有model层,都是放在了同一个main.go文件中,如果写项目的话,还得自己去拆文件,拆代码,经过查询和自己总结,下面放一个目录框架

总体目录结构

按照业务流程顺序,解释说明

1、加载自定义封装函数文件、数据库、redis

package main

import (
	"ginchat/router"
	"ginchat/utils"
)

func main() {
	utils.InitConfig()
	utils.InitMysql()
	utils.InitRedis()
	r := router.Router()

	r.Run(":8081")
}

依次的三个函数

system_init.go文件里面

package utils

import (
	"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.DB
	err error
	Red *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 router

import (
	"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:0
  poolSize:30
  minIdleConn:30

说明一下,dns里面的参数

账号:密码@tcp(ip:端口号)/数据库名字?xxxxxxxx

4、然后,预备的工作就完成了。另外,有一个sql文件下面的testGorm.go文件

package main

import (
	"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 models

import (
	"fmt"
	"ginchat/utils"
	"gorm.io/gorm"
)

type UserBasic struct {
	gorm.Model
	Name          string
	Password      string
	Phone         string `valid:"matches(^1[3-9]{1}\\d{9}$)"`
	Email         string `valid:"email"`
	Avatar        string //头像
	Identity      string
	ClientIp      string
	Salt          string
	ClientPort    string
	LoginTime     uint64
	HeartbeatTime uint64
	LoginOutTime  uint64
	IsLogout      bool
	DeviceInfo    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 service

import (
	"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 = salt
	models.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 utils

import (
	"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 utils

import (
	"encoding/json"
	"net/http"
)

type H struct {
	Code  int
	Msg   string
	Data  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

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

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

相关文章

ssh免密登录 ssh公钥分发 ssh密钥生成

在连接服务器时,我们会被要求输入用户名对应的密码,如下👇: 如果我们要登录的服务器是常用服务器,那么每次登录输入密码就会比较麻烦。那么如何免密登录呢?那就需要使用到rsa公私钥认证了。 生成rsa密钥…

vue 指定区域可拖拽的限定拖拽区域的div(如仅弹窗标题可拖拽的弹窗)

<template><div class"container" ref"container"><div class"drag-box" v-drag><div class"win_head">弹窗标题</div><div class"win_content">弹窗内容</div></div><…

vivado导出时序报告为excel文件的方法

1、打开implementation下的report timing summary 2、选择要看的时钟右键点击report_timing 3、在新打开的timing窗口中&#xff0c;选择setup或者hold&#xff0c;选中一条路径右键&#xff0c;点击export to spreadsheet&#xff0c;此时就可以存为table.xlsx文件

【MySQL】权限控制

DCL-权限控制 查询权限 show grants for 用户名主机名;授予权限 grant 权限列表 on 数据库名.表名 to 用户名主机名;grant all on test.* to user%; %是通配符&#xff0c;表示任意主机。撤销权限 revoke 权限列表 on 数据库名.表名 from 用户名主机名;revoke all on test.*…

旅游平台day02

1. 用户注册 概述&#xff1a; 常见的注册方式&#xff1a;邮箱注册、手机号注册、昵称注册、或者以上几种同时支持 本项目仅仅支持手机号注册 需求&#xff1a; 项目启动后&#xff0c;访问regist.html进入注册页面 手机号校验 前后台都需要对手机号进行校验 前端校验&am…

HashMap学习和线程安全的HashMap

HashMap的底层数据结构&#xff1f; HashMap在JDK1.8里面的Node数组加链表加红黑树&#xff0c;当链表长度大于8且数组长度大于64&#xff0c;链表转化为红黑树。当红黑树节点数小于6&#xff0c;红黑树转化为链表。在JDK1.7中是数组加链表。 为什么要用红黑树&#xff1f; 当…

react 第一个项目

sudo npx create-react-app reactdemo01 npx node.js工具 create-react-app 核心包&#xff08;固定写法&#xff09;用于创建react项目 后跟项目名层 启动一个新的 React 项目 – React 中文文档 //项目的根组件 //App -> index.js ->/Users/king/Documents/react…

芯片新闻-Global Semiconductor Sales Increase 5.3% Year-to-Year in November

11 月标志着一年多以来市场同比增长的第一个月&#xff1b;全球芯片销量环比增长2.9% 华盛顿——一月。 2024 年 12 月 9 日——半导体行业协会 (SIA) 今天宣布&#xff0c;2023 年 11 月全球半导体行业销售额总计 480 亿美元&#xff0c;比 2022 年 11 月的 456 亿美元总额增…

rust跟我学七:获取外网IP地址

图为RUST吉祥物 大家好,我是get_local_info作者带剑书生,这里用一篇文章讲解get_local_info是怎么获取到本机的外网IP地址。 首先,先要了解get_local_info是什么? get_local_info是一个获取linux系统信息的rust三方库,并提供一些常用功能,目前版本0.2.4。详细介绍地址:[…

FPGA 原理图引脚标识细节

BGA引脚表示 1.1 FPGA此引脚要正确和清晰&#xff0c;会在“Package Pin”中用到次物理接口 1.2, MCU 只用管对应的GPIO逻辑接口就可以了 1.3&#xff0c;引脚名标识出bank, PS/PL, signal/differential 标识Bank电平 标识出对应Bank的电平&#xff0c;在电路设计中可以清晰…

C#调用Newtonsoft.Json将bool序列化为int

使用Newtonsoft.Json将数据对象序列化为Json字符串时&#xff0c;如果有布尔类型的属性值时&#xff0c;一般会将bool类型序列化为字符串&#xff0c;true值序列化为true&#xff0c;false值序列化为false。如下面的类型序列化后的结果如下&#xff1a; public class UserInfo…

量化研究员!你应该如何写一手好代码

即使是Quant Researcher&#xff0c; 写一手高质量的代码也是非常重要的。再好的思路&#xff0c;如果不能正确地实现&#xff0c;都是没有意义的。 写一手高质量的代码的意义&#xff0c;对Quant developer来讲就更是自不待言了。这篇笔记就介绍一些python best practice。 始…

npm install 无反应 npm run serve 无反应

说明情况&#xff1a;其实最开始我就是发现我跟着黑马的苍穹外卖的前端day2的环境搭建做的时候&#xff0c;到这一步出现了问题&#xff0c;无论我怎么 npm install 和 npm run serve 都没有像黑马一样有很多东西进行加载&#xff0c;因此我换了一种方法 1.在这个文件夹下cmd …

CSS 设置背景图片

文章目录 设置背景颜色设置背景图片背景图片偏移量计算原点背景图片尺寸设置背景图片位置设置背景图片重复方式设置背景范围设置背景图片是否跟随元素移动测试背景图片 本文概念部分参考&#xff1a;CSS背景background设置 设置背景颜色 background-color 设置背景颜色 设置…

【面试合集】说说你对 linux 用户管理的理解?相关的命令有哪些?

面试官&#xff1a;说说你对 linux 用户管理的理解&#xff1f;相关的命令有哪些&#xff1f; 一、是什么 Linux是一个多用户的系统&#xff0c;允许使用者在系统上通过规划不同类型、不同层级的用户&#xff0c;并公平地分配系统资源与工作环境 而与 Windows 系统最大的不同…

表的增删改查 进阶(一)

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f525;个人专栏&#xff1a;MySql&#x1f4d5;格言&#xff1a;那些在暗处执拗生长的花&#xff0c;终有一日会馥郁传香欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 1.数据库约束 约束类型 NOT NUll 约束 UNIQUE 约束 …

【Qt-license】误操作qt下载导致只能安装商业版试用十天,无法安装社区版

背景&#xff1a; 原本是为了学习qml&#xff0c;需要下载一个design studio&#xff0c;而这个需要比较新版的安装程序&#xff0c;但新版的安装程序官方都是online安装。于是从官网找下载链接。毕竟是英文的&#xff0c;又心急&#xff0c;误打误撞中我选择了商业版试用。 其…

2024华数杯B题四小问完整思路+四问数据代码+数据可视化图表

ICM B 题&#xff1a;光伏发电 完整资料在文末获取 该题目出题的难度与方向都与美赛 ICM 的题型高度相似&#xff0c;将本次竞赛当做美赛的 练手赛&#xff0c;个人认为是非常合适的一种选择。同时 28 号就可以出成绩&#xff0c;也可以在美赛前 实现查漏补缺&#xff0c;提…

dolphinscheduler分布式集群部署指南(小白版)

1.Apache DolphinScheduler概述 官方文档地址&#xff1a;https://dolphinscheduler.apache.org/zh-cn/docs/3.1.9 1.1.DolphinScheduler简介 摘自官网&#xff1a;Apache DolphinScheduler 是一个分布式易扩展的可视化DAG工作流任务调度开源系统。适用于企业级场景&#xf…

5-数组-矩阵置零

这是数组的第5篇算法&#xff0c;力扣链接。 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0…