使用 GORM(Go 的 ORM 库)连接数据库:基于Gin框架和GORM 实现用户的增删改查 | 豆包MarsCode AI刷题

69 阅读13分钟

项目流程

配置项

配置内容放在config.json内

{
    "app_config": {
        "app_name": "商品管理系统",
        "host": "xx.xx.xx.xx",
        "port": "xx",
        "database": {
            "database": "admin_test_back",
            "user": "root",
            "password": "xxx",
            "host": "localhost",
            "port": "3306",
            "charset": "utf8mb4",
            "parse_time": true,
            "loc": "Local"
        }
    }
}

包括了项目的配置以及数据库的配置,并在config.go中进行配置的读取

package config
​
import (
    "encoding/json"
    "log"
    "os"
)
​
var GlobalConfig *Config
​
type Config struct {
    AppConfig *AppConfig `json:"app_config"`
}
​
type AppConfig struct {
    AppName  string    `json:"app_name"`
    Host     string    `json:"host"`
    Port     string    `json:"port"`
    Database *Database `json:"database"`
}
​
type Database struct {
    Database  string `json:"database"`
    User      string `json:"user"`
    Password  string `json:"password"`
    Host      string `json:"host"`
    Port      string `json:"port"`
    Charset   string `json:"charset"`
    ParseTime bool   `json:"parse_time"`
    Loc       string `json:"loc"`
}
​
func InitConfig() {
    path := "config.json"
    read, err := os.ReadFile(path)
    if err != nil {
        log.Fatalln(err)
    }
    c := new(Config)
    if err := json.Unmarshal(read, c); err != nil {
        log.Fatalln(err)
    }
    //全局赋值
    GlobalConfig = c
}
​

定义三个结构体,第一个是Config是总体的结构体,第二个AppConfig是项目的结构体,第三个Database是数据库的结构体。

接着在InitConfig中读取config.json中的配置内容,将它们赋值给一个新创建的Config结构体c,最后将c赋值给全局变量GlobalConfig,以后调用配置的时候只需将config.go这个包导入然后使用GlobalConfig即可。

数据库初始化

在db文件夹的mysql.go中进行数据库初始化

var DB *gorm.DB
​
func InitMysql() {
    database := config.GlobalConfig.AppConfig.Database
    parseTimeStr := "False"
    if database.ParseTime {
        parseTimeStr = "True"
    }
    dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=%s&loc=%s", database.User, database.Password, database.Host, database.Port, database.Database, database.Charset, parseTimeStr, database.Loc)
    db, err := gorm.Open("mysql", dsn)
    if err != nil {
        log.Fatalln("mysql connect failed", err)
    }
    DB = db
}
​

首先定义一个全局变量DB,类型是*gorm.DB,使用了gorm,今后需要操作数据库的时候将mysql.go包导入然后使用DB即可。

在InitMysql函数中进行数据库初始化

func InitMysql() {
    database := config.GlobalConfig.AppConfig.Database
    parseTimeStr := "False"
    if database.ParseTime {
        parseTimeStr = "True"
    }
    dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=%s&loc=%s", database.User, database.Password, database.Host, database.Port, database.Database, database.Charset, parseTimeStr, database.Loc)
    db, err := gorm.Open("mysql", dsn)
    if err != nil {
        log.Fatalln("mysql connect failed", err)
    }
    DB = db
}

调用GlbalConfig中的Database对数据库进行初始化,dsn即为数据库的相关内容,然后调用gorm.Open("mysql", dsn)打开mysql数据库连接,返回一个数据库实体db,类型是*gorm.DB,最后将db赋值给全局变量DB。

main函数

在main函数中运行项目,首先使用init函数进行初始化

func init() {
    // 初始化配置文件
    config.InitConfig()
    // 初始化mysql
    db.InitMysql()
    // 初始化redis
    // redis.InitRedis(config.GlobalConfig.AppConfig)
}

接着在main函数中运行项目

func main() {
    // 获取应用配置文件
    c := config.GlobalConfig.AppConfig
    r := gin.Default()
​
    r.Use(middleware.Cors())
    // 注册路由
    RegisterRouter(r)
    if err := r.Run(fmt.Sprintf(":%s", c.Port)); err != nil {
        log.Fatalln(err)
    }
}

使用了middleware中的中间件cors来允许跨域请求

然后使用同一个包下的router.go中的RegisterRouter(r)来注册路由

最后r.Run运行项目

router.go

此文件中包含了一个 路由注册函数,用于在 Gin 框架中配置 HTTP 路由及其对应的处理逻辑。每个路由都绑定到特定的 URL 路径、HTTP 方法以及对应的中间件和控制器处理函数。

package main
​
import (
    "admin_test_back/controller"
    "admin_test_back/form"
    "admin_test_back/middleware"
    "admin_test_back/model"
    "net/http""github.com/gin-gonic/gin"
)
​
func RegisterRouter(engine *gin.Engine) {
​
    engine.POST("/register", middleware.Bind("user", &form.UserRegisterForm{}), controller.UserRegister)
​
    engine.POST("/login", middleware.Bind("user", &form.UserLoginForm{}), controller.UserLogin)
​
    engine.GET("/users/:id", middleware.Auth(), controller.UserGet)
​
    engine.GET("/users/self", middleware.Auth(), controller.UserGetSelf)
​
    engine.PUT("/users", middleware.Auth(), middleware.Bind("user", &model.User{}), controller.UserPut)
​
    engine.GET("/users", middleware.Auth(), controller.UserListGet)
​
    engine.DELETE("/users/:id", middleware.Auth(), controller.UserDelete)
}

函数签名

func RegisterRouter(engine *gin.Engine)
  • 参数:

    • engine:Gin 的主路由引擎对象,用于注册路由。
  • 功能:

    • 将一系列路由规则添加到传入的 Gin 引擎中。

关键点

  1. 中间件的作用

    • middleware.Bind:负责数据绑定和验证。
    • middleware.Auth:负责用户身份认证,确保只有合法用户可以访问受保护的路由。
  2. 控制器的分层

    • 控制器函数负责处理具体的业务逻辑,与路由和中间件分离,符合分层设计原则。
  3. RESTful 风格

    • 路由设计符合 RESTful 风格,资源名称(如 /users)对应不同的 HTTP 方法,实现增删改查操作。

中间件

使用了三个中间件auth.go,bind.go,cors.go

auth.go

在auth.go中实现简单的JWT认证逻辑

package middleware
​
import (
    "admin_test_back/common"
    "strings""github.com/gin-gonic/gin"
)
​
func Auth() gin.HandlerFunc {
    return func(c *gin.Context) {
        // TODO: implement authentication logic
        tokenString := c.GetHeader("Authorization")
        if tokenString == "" {
            c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
            return
        }
        if !strings.HasPrefix(tokenString, "Bearer ") {
            c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
            return
        }
        tokenString = strings.TrimPrefix(tokenString, "Bearer ")
        token, claims, err := common.ParaseToken(tokenString)
        if err != nil || !token.Valid {
            c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
            return
        }
        c.Set("id", claims.Id)
        c.Next()
    }
}

函数签名

func Auth() gin.HandlerFunc
  • 返回值:返回一个 gin.HandlerFunc 类型的函数,可用于 Gin 的中间件链。
  • 用途:用于验证客户端请求中的 Authorization 头部是否包含有效的 JWT(JSON Web Token)。

功能逻辑

  1. 获取 Authorization 头部

    tokenString := c.GetHeader("Authorization")
    if tokenString == "" {
        c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
        return
    }
    
    • 从 HTTP 请求头中获取 Authorization 字段。
    • 如果没有找到,直接返回 401 Unauthorized 响应,阻止后续请求。
  2. 校验 Bearer 前缀

    if !strings.HasPrefix(tokenString, "Bearer ") {
        c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
        return
    }
    tokenString = strings.TrimPrefix(tokenString, "Bearer ")
    
    • 检查 Authorization 字段是否以 Bearer 开头。
    • 如果没有正确的前缀,也返回 401 Unauthorized
    • 去掉前缀,提取实际的 JWT 字符串。
  3. 解析和验证 JWT

    token, claims, err := common.ParaseToken(tokenString)
    if err != nil || !token.Valid {
        c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
        return
    }
    
    • 调用 common.ParseToken(一个自定义函数解析JWT)解析 JWT,并验证其有效性。
    • 如果解析失败或 token 无效,返回 401 Unauthorized
  4. 将用户信息存入上下文

    c.Set("id", claims.Id)
    c.Next()
    
    • 从解析后的 claims(JWT 的负载)中提取 Id,并将其存入 Gin 的上下文中,方便后续的处理函数使用。
    • 调用 c.Next() 继续执行后续的中间件和处理函数。

JWT 身份认证:确保只有持有有效 JWT 的请求可以访问受保护的资源。

用户信息传递:提取 JWT 中的用户 ID,并在后续处理中使用(例如查询数据库中的用户信息)。

bind.go

通用的 Bind 中间件函数,用于绑定和验证传入的请求参数,并在验证通过后将解析的结果存储到上下文中,供后续处理器函数使用。

函数签名

func Bind(key string, val any) gin.HandlerFunc
  • 参数

    • key:字符串类型,用作在上下文中存储数据的键。
    • val:任意类型,用于接收绑定和解析后的数据(通常是结构体指针)。
  • 返回值

    • 返回一个 gin.HandlerFunc,这是 Gin 中间件的标准类型。

内部逻辑

  1. 绑定和验证参数

    if err := c.ShouldBind(val); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        c.Abort()
    }
    
    • 调用 c.ShouldBind(val) 尝试将请求参数绑定到 val 中(支持 JSON、表单、查询参数等多种格式)。
    • 如果绑定失败,返回 400 错误,包含错误信息,并调用 c.Abort() 中止后续的中间件和路由处理器函数。
  2. 存储解析后的数据

    c.Set(key, val)
    
    • 如果绑定成功,将 valkey 为键存入上下文中,供后续处理函数使用。
  3. 继续后续处理

    c.Next()
    
    • 调用 c.Next() 继续执行后续的中间件或处理器函数。

cors.go

实现 跨域资源共享(CORS: Cross-Origin Resource Sharing) ,它允许不同源的客户端访问服务器的资源。例如,一个运行在 http://example.com 的前端应用可以通过 CORS 请求访问 http://api.example.com 提供的 API。

CORS 背景

  • 跨域问题:浏览器出于安全考虑,默认禁止来自不同源(域名、协议、端口)的请求访问。

    • 同源策略限制了跨域请求。
  • CORS 是一种机制,通过设置特定的 HTTP 响应头,允许服务器控制哪些跨域请求是被允许的。

主要功能

  1. 允许跨域请求

    c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
    
    • Access-Control-Allow-Origin 指定允许哪些来源访问资源。
    • "*" 表示允许所有来源跨域;可以改为特定域名(如 "http://example.com")。
  2. 指定支持的 HTTP 方法

    c.Header("Access-Control-Allow-Methods", "POST, GET, UPDATE, PUT, DELETE")
    
    • Access-Control-Allow-Methods 指定允许客户端使用的请求方法(如 GET、POST)。
  3. 指定允许的请求头

    c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-TOKEN")
    
    • Access-Control-Allow-Headers 指定客户端可以发送的自定义头信息(如 AuthorizationX-TOKEN)。
  4. 允许客户端获取的响应头

    c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
    
    • Access-Control-Expose-Headers 指定客户端可以访问的响应头信息。
  5. 处理 OPTIONS 预检请求

    if method == "OPTIONS" {
        c.AbortWithStatus(http.StatusNoContent)
    }
    
    • 预检请求(Preflight Request):

      • 浏览器在发送实际请求前,会使用 OPTIONS 方法发送一个预检请求。
      • 预检请求用于检查服务器是否允许目标请求。
  6. 继续执行后续中间件或逻辑

    c.Next()
    
    • 在处理完跨域设置后,继续执行后续的中间件或路由逻辑。

CORS 头部总结

Header Name作用
Access-Control-Allow-Origin指定允许的跨域来源
Access-Control-Allow-Methods指定允许的 HTTP 方法
Access-Control-Allow-Headers指定允许的自定义请求头
Access-Control-Expose-Headers指定允许客户端访问的响应头
Access-Control-Allow-Credentials是否允许发送认证信息(如 Cookie)

实际用途

  • 前后端分离项目:前端和后端通常运行在不同域上,CORS 解决跨域请求问题。
  • 开放 API:允许外部系统通过跨域请求访问资源。
  • 调试与开发:本地开发中,前端运行在 localhost 上,访问后端接口需要跨域支持。

common

common文件夹里包含了jwt.go和utils.go,分别用于jwt用户鉴权以及对用户密码进行加密和验证

jwt.go

package common
​
import (
    "strconv"
    "time""github.com/dgrijalva/jwt-go"
)
​
var validTime time.Duration = (7 * 24) // hoursvar jwtKey = []byte("WJDSBrewgs12093fads")
​
type Claims struct {
    Id string
    jwt.StandardClaims
}
​
// 使用user.ID获取token
func ReleaseToken(id uint) (string, error) {
    idString := strconv.Itoa(int(id))
    expirationTime := time.Now().Add(validTime * time.Hour)
    claims := &Claims{
        Id: idString,
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: expirationTime.Unix(),
            IssuedAt:  time.Now().Unix(),
            Issuer:    "admin_test_back",
            Subject:   "user token",
        },
    }
​
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    tokenString, err := token.SignedString(jwtKey)
    if err != nil {
        return "", err
    }
​
    return tokenString, nil
}
​
func ParaseToken(tokenString string) (*jwt.Token, *Claims, error) {
    claims := &Claims{}
​
    token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (i interface{}, err error) {
        return jwtKey, err
    })
​
    return token, claims, err
}

ReleaseToken函数使用用户的id来获取token并返回token字符串

ParaseToken函数对传入的tokenString进行验证

utils.go

package common
​
import "golang.org/x/crypto/bcrypt"// 加密
func CalculatePasswordHash(pwd string) (string, error) {
    hash, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)
    if err != nil {
        return "", err
    }
    return string(hash), nil
}
​
// 验证
func CheckPasswordHash(password, hash string) error {
    return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
}

CalculatePasswordHash函数对传入的字符串进行加密并返回加密后的字符串

CheckPasswordHash函数对传入的密码进行验证,看是否与加密后的密码一致

model

model文件夹中包含user.go文件,用于定义User的结构

package model
​
import "github.com/jinzhu/gorm"type User struct {
    gorm.Model
    UserName     string `json:"user_name"`
    UserPassword string `json:"user_password"`
    UserRealname string `json:"user_realname"`
    UserPhone    string `json:"user_phone"`
    UserAge      int    `json:"user_age"`
    UserSex      int    `json:"user_sex"`
    UserRoleId   int    `json:"user_role_id"`
}

form

form文件夹中包含了userForm.go,用于定义前端返回的表单的结构,包括了用户注册的表单和用户登录的表单

package form
​
type UserRegisterForm struct {
    UserName     string `json:"user_name"`
    UserPassword string `json:"user_password"`
    UserRealname string `json:"user_realname"`
    UserPhone    string `json:"user_phone"`
    UserAge      int    `json:"user_age"`
    UserSex      int    `json:"user_sex"`
}
​
type UserLoginForm struct {
    UserName     string `json:"user_name"`
    UserPassword string `json:"user_password"`
}

userDB.go

db文件夹下面的userDB.go用于对数据库进行操作,包括了CreateOne,FindOneByName,FindOneById,UpdateOne,GetUserList,DeleteOne等功能。

package db
​
import (
    "admin_test_back/model"
)
​
type UserDB struct{}
​
func (u *UserDB) CreateOne(user *model.User) error {
    if err := DB.Create(user).Error; err != nil {
        return err
    }
    return nil
}
​
func (u *UserDB) FindOneByName(userName string) (*model.User, error) {
    user := &model.User{}
    if err := DB.Model(&model.User{}).Where("user_name = ?", userName).Find(user).Error; err != nil {
        return nil, err
    }
    return user, nil
}
func (u *UserDB) FindOneById(id uint) (*model.User, error) {
    user := &model.User{}
    if err := DB.Model(&model.User{}).Where("id = ?", id).Find(user).Error; err != nil {
        return nil, err
    }
    return user, nil
}
func (u *UserDB) UpdateOne(user *model.User) error {
    if err := DB.Model(&user).Save(&user).Error; err != nil {
        return err
    }
    // if err := DB.Model(&user).Updates(user).Error; err != nil {
    //  return err
    // }
    return nil
}
​
func (u *UserDB) GetUserList() (*[]model.User, error) {
    var users []model.User
    if err := DB.Model(&model.User{}).Find(&users).Error; err != nil {
        return nil, err
    }
    return &users, nil
}
​
func (u *UserDB) DeleteOne(id uint) error {
    if err := DB.Model(&model.User{}).Delete(&model.User{}, id).Error; err != nil {
        return err
    }
    return nil
}

CreateOne对传入的user结构体进行操作,将它添加进数据库中

FindOneByName将传入的userName在数据库中进行查找,返回对应的用户user

FindOneById将传入的id在数据库中进行查找,返回对应的user

UpdateOne对传入的user结构体进行操作,将它在数据库中的信息进行修改

GetUserList将数据库中的所有数据放入传入的结构体参数中

DeleteOne根据传入的id查找数据库中对应的数据并删除

controller

controller文件夹中的userController.go包含了各种控制器函数,负责处理具体的业务逻辑

package controller
​
import (
    "admin_test_back/common"
    "admin_test_back/db"
    "admin_test_back/form"
    "admin_test_back/model"
    "fmt"
    "net/http"
    "strconv""github.com/gin-gonic/gin"
)
​
func UserRegister(c *gin.Context) {
    //获取表单中的数据,存入userForm中
    userForm := c.MustGet("user").(*form.UserRegisterForm)
    //判断用户是否已存在,通过账号判断
    _, err := new(db.UserDB).FindOneByName(userForm.UserName)
    if err == nil {
        c.JSON(http.StatusConflict, gin.H{
            "message": "用户名已存在",
        })
        return
    }
    //将userForm存入数据库,需要创建model.User实例
    //加密密码
    hashPwd, err := common.CalculatePasswordHash(userForm.UserPassword)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "注册失败",
        })
        return
    }
    user := &model.User{
        UserName:     userForm.UserName,
        UserPassword: hashPwd,
        UserRealname: userForm.UserRealname,
        UserPhone:    userForm.UserPhone,
        UserAge:      userForm.UserAge,
        UserSex:      userForm.UserSex,
        UserRoleId:   0,
    }
    //存入数据库
    if err := new(db.UserDB).CreateOne(user); err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "注册失败",
        })
        return
    }
​
    token, err := common.ReleaseToken(user.ID)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "注册成功但登录失败",
        })
        return
    }
    c.JSON(http.StatusOK, gin.H{
        "token": token,
    })
}
​
func UserLogin(c *gin.Context) {
    //获取表单中的数据,存入userForm中
    userForm := c.MustGet("user").(*form.UserLoginForm)
    //判断用户是否存在
    user, err := new(db.UserDB).FindOneByName(userForm.UserName)
    if err != nil {
        c.JSON(http.StatusUnauthorized, gin.H{
            "message": "用户名或密码错误",
        })
        return
    }
    //判断密码是否正确
    err = common.CheckPasswordHash(userForm.UserPassword, user.UserPassword)
    if err != nil {
        c.JSON(http.StatusUnauthorized, gin.H{
            "message": "用户名或密码错误",
        })
        return
    }
    token, err := common.ReleaseToken(user.ID)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "登录失败",
        })
        return
    }
    // //获取用户角色
    // role := ""
    // if user.UserRoleId == 0 {
    //  role = "user"
    // } else {
    //  role = "admin"
    // }
    c.JSON(http.StatusOK, gin.H{
        "token": token,
        "user":  user,
    })
}
​
func userGet(c *gin.Context, idStr string) {
    id, err := strconv.ParseUint(idStr, 10, 64)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "参数错误",
        })
        return
    }
    user, err := new(db.UserDB).FindOneById(uint(id))
    if err != nil {
        c.JSON(http.StatusNotFound, gin.H{
            "message": "获取用户信息失败",
        })
        return
    }
    c.JSON(http.StatusOK, gin.H{
        "user": user,
    })
}
​
func UserGet(c *gin.Context) {
    idStr := c.Param("id")
    userGet(c, idStr)
}
​
func UserGetSelf(c *gin.Context) {
    idStr := c.MustGet("id").(string)
    userGet(c, idStr)
}
func UserPut(c *gin.Context) {
    userForm := c.MustGet("user").(*model.User)
    user, err := new(db.UserDB).FindOneById(userForm.ID)
    fmt.Println(userForm.ID, userForm.UserName, userForm.UserRealname, userForm.UserPhone, userForm.UserAge, userForm.UserSex, userForm.UserRoleId, userForm.CreatedAt, userForm.UpdatedAt)
    if err != nil {
        c.JSON(http.StatusNotFound, gin.H{
            "message": "获取用户信息失败",
        })
        return
    }
    if err := new(db.UserDB).UpdateOne(userForm); err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "更新用户信息失败",
        })
        return
    }
    fmt.Println(user)
    c.JSON(http.StatusOK, gin.H{
        "message": "更新用户信息成功",
    })
}
​
func UserListGet(c *gin.Context) {
    users, err := new(db.UserDB).GetUserList()
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "获取用户列表失败",
        })
        return
    }
    c.JSON(http.StatusOK, gin.H{
        "users":   users,
        "message": "获取用户列表成功",
    })
}
​
func UserDelete(c *gin.Context) {
    idStr := c.Param("id")
    id, err := strconv.ParseUint(idStr, 10, 64)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "参数错误",
        })
        return
    }
    user, err := new(db.UserDB).FindOneById(uint(id))
    if err != nil {
        c.JSON(http.StatusNotFound, gin.H{
            "message": "获取用户信息失败",
        })
        return
    }
    if err = new(db.UserDB).DeleteOne(user.ID); err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "message": "删除用户失败",
        })
        return
    }
    c.JSON(http.StatusOK, gin.H{
        "message": "删除用户成功",
    })
}

UserRegister函数获取表单中的数据,赋值到userForm中然后存入数据库进行用户注册。首先会查询数据库信息,判断用户是否已经存在,如果不存在首先会将密码进行加密,然后会将此数据存入数据库,最后返回一个token给前端。

UserLogin获取表单中的数据,赋值到userForm中,首先会查找数据库,判断用户是否存在,接着判断密码是否正确,最后返回一个token以及用户结构体给前端。

userGet会根据传入的id在数据库中查找此用户是否存在,如果存在最后会将此用户结构体返回给前端。

UserGet会获取url中传入的参数,即?之后的内容,然后调用userGet函数获取用户信息。

UserGetSelf会获取上下文中的id,调用userGet函数获取用户信息,此函数是实现返回当前用户的信息,会在url中没有参数传入的时候调用。

UserPut会从上下文中获取user结构体,然后在数据库中根据id查找是否存在此用户,如果存在则会将此结构体传入数据库进行用户信息修改。

UserListGet会获取数据库中所有用户数据,然后返回给前端。

UserDelete会根据url中传入的id参数在数据库中查找,如果找到了用户,则将此用户删除并返回删除用户成功的信息给前端。

总结

完成后端开发后,可以使用swagger进行接口文档编写和测试,也可以自己使用vue3进行前端页面设计并与后端进行交互。本项目使用到了Gin框架以及Gorm的使用,使用MySQL进行数据的存储,同时也用到了JWT进行鉴权和权限管理。