gin+gorm增删改查目录框架

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

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

总体目录结构

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

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

Go 复制代码
package main

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

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

	r.Run(":8081")
}

依次的三个函数

system_init.go文件里面

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、加载路由文件

Go 复制代码
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中

Go 复制代码
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文件

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{}

Go 复制代码
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层

Go 复制代码
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

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
}
Go 复制代码
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

相关推荐
不爱说话郭德纲4 小时前
聚焦 Go 语言框架,探索创新实践过程
go·编程语言
0x派大星1 天前
【Golang】——Gin 框架中的 API 请求处理与 JSON 数据绑定
开发语言·后端·golang·go·json·gin
get2001 天前
Gin 框架中间件详细介绍
中间件·gin
bigbig猩猩1 天前
Gin 框架中的表单处理与数据绑定
驱动开发·gin
IT书架1 天前
golang高频面试真题
面试·go
郝同学的测开笔记1 天前
云原生探索系列(十四):Go 语言panic、defer以及recover函数
后端·云原生·go
荣~博客2 天前
Golang语言整合jwt+gin框架实现token
开发语言·golang·gin
拧螺丝专业户2 天前
gin源码阅读(2)请求体中的JSON参数是如何解析的?
前端·json·gin
秋落风声2 天前
【滑动窗口入门篇】
java·算法·leetcode·go·哈希表
留乘船3 天前
使用gin -gorm-jwt-中间件拦截的一个小项目
开发语言·学习·中间件·golang·gin