GIN试玩:GORM增删改查分页

本文介绍了一个基于Golang实现的用户角色管理系统的设计与实现细节,涵盖了从数据库表到结构体的转换、业务逻辑处理和服务层设计等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先,将数据库表转换为结构体,在线转结构体

Model

// Model/user.go
type UserRole struct {
	Id int `gorm:"column:id" db:"id" json:"id" form:"id"`
	Keyword string `gorm:"column:keyword" db:"keyword" json:"keyword" form:"keyword"` //角色关键字
	Name string `gorm:"column:name" db:"name" json:"name" form:"name"` //角色名称
	Level int `gorm:"column:level" db:"level" json:"level" form:"level"` //角色等级
	CreateBy string `gorm:"column:create_by" db:"create_by" json:"createBy" form:"create_by"` //创建人
	CreateTime string `gorm:"column:create_time" db:"create_time" json:"createTime" form:"create_time"` //创建时间
	UpdateBy string `gorm:"column:update_by" db:"update_by" json:"updateBy" form:"update_by"` //更新人
	UpdateTime string `gorm:"column:update_time" db:"update_time" json:"updateTime" form:"update_time"` //更新时间
}

数据库dataTime格式转换为结构体为Time.time,处理起来极为麻烦,还要修改mysql的配置,建议手动修改为string

如果与前端交互的字段为驼峰格式,手动修改json

Service

// Service/user.go
type UserService struct {
}
// 相当于声明一个命名空间
var UserServer UserService
// 查询
func (t *UserService) RoleList(params string, pageNo int, pageSize int) ([]Model.UserRole, int) {
	var total int
	db := GetDb().Model(&Model.UserRole{}).Where(params).Count(&total).Limit(pageSize).Offset((pageNo - 1) * pageSize)
	var list []Model.UserRole
	db = db.Find(&list)
	if db.Error != nil {
		fmt.Println(db.Error)
	}
	return list, total
}
// 新增、编辑
func (t *UserService) RoleEdit(model Model.UserRole, isEdit bool) error {
	db := GetDb()
	if isEdit {
		db = db.Save(model)
	} else {
		// 如果id是自增的,务必带&
		db = db.Create(&model) 
	}
	if db.Error != nil {
		return db.Error
	}
	return nil
}
// 删除
func (t *UserService) RoleDel(ids []int) error {
	db := GetDb().Model(&Model.UserRole{})
	db = db.Delete(Model.UserRole{}, ids)
	if db.Error != nil {
		return db.Error
	}
	return nil
}

Controller

// Controller/user.go
type UserController struct {
}
var UserControl = &UserController{}

func (t *UserController) RoleList(c *gin.Context) {
	// 解析前端参数
	params, pageNo, pageSize := PackageRequestParams(c)
	res, total := Service.UserServer.RoleList(params, pageNo, pageSize)
	ResponseSuccessMap(c, map[string]interface{}{
		"records": res,
		"total":   total,
	})
}

func (t *UserController) RoleEdit(c *gin.Context) {
	data, err := ioutil.ReadAll(c.Request.Body)
	CheckError(err)
	var msg Model.UserRole
	json.Unmarshal(data, &msg)
	user, _ := GetCurUserinfo(c)
	// time.Time 与数据库与前端三者之间转换实在太麻烦,所以定义为string, updateTime为空时指定一个特定时间,前端显示时过滤掉
	if msg.Id == 0 {
		msg.CreateBy = user.Username
		msg.CreateTime = time.Now().Format("2006-01-02 15:04:05")
		msg.UpdateTime = "1010-10-10 00:00:00"
	} else {
		msg.UpdateBy = user.Username
		msg.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
	}
	if err := Service.UserServer.RoleEdit(msg, msg.Id != 0); err == nil {
		ResponseSuccess(c, "success")
	} else {
		ResponseError(c, err.Error())
	}
}

func (t *UserController) RoleDel(c *gin.Context) {
	data, err := ioutil.ReadAll(c.Request.Body)
	CheckError(err)
	var msg struct {
		Ids []int
	}
	json.Unmarshal(data, &msg)
	if err := Service.UserServer.RoleDel(msg.Ids); err == nil {
		ResponseSuccess(c, "success")
	} else {
		ResponseError(c, err.Error())
	}
}

公用方法

// Controller/common.go
type RequestCondition struct {
	Column string
	Value  string
	Type   string
}
// 前端列表请求参数格式
type RequestListData struct {
	PageNo    int
	PageSize  int
	Condition []RequestCondition
}
func ResponseSuccess(c *gin.Context, data string) {
	c.JSON(http.StatusOK, gin.H{
		"code":    "200",
		"message": "success",
		"data":    data,
		"success": true,
	})
}
func ResponseSuccessMap(c *gin.Context, data map[string]interface{}) {
	c.JSON(http.StatusOK, gin.H{
		"code":    "200",
		"message": "success",
		"data":    data,
		"success": true,
	})
}
func ResponseError(c *gin.Context, data string) {
	c.JSON(http.StatusOK, gin.H{
		"code":    "500",
		"message": data,
		"data":    "",
		"success": false,
	})
}
func CheckError(e error) {
	if e != nil {
		fmt.Println(e.Error())
	}
}
// 将前端请求参数转换为 grom where语句
func PackageRequestParams(c *gin.Context) (string, int, int) {
	data, err := ioutil.ReadAll(c.Request.Body)
	CheckError(err)
	var req RequestListData
	json.Unmarshal(data, &req)
	var res []string
	for _, value := range req.Condition {
		var c string
		key := snakeString(value.Column)
		switch value.Type {
		case "eq":
			c = key + " = " + "'" + value.Value + "'"
			break
		case "like":
			c = key + " like " + "'%" + value.Value + "%'"
			break
		case "gt":
			c = key + " > " + value.Value
			break
		case "lt":
			c = key + " < " + value.Value
			break
		}
		res = append(res, c)
	}
	return strings.Join(res, " and "), req.PageNo, req.PageSize
}
// 驼峰转蛇形
func snakeString(s string) string {
	data := make([]byte, 0, len(s)*2)
	j := false
	num := len(s)
	for i := 0; i < num; i++ {
		d := s[i]
		// or通过ASCII码进行大小写的转化
		// 65-90(A-Z),97-122(a-z)
		//判断如果字母为大写的A-Z就在前面拼接一个_
		if i > 0 && d >= 'A' && d <= 'Z' && j {
			data = append(data, '_')
		}
		if d != '_' {
			j = true
		}
		data = append(data, d)
	}
	//ToLower把大写字母统一转小写
	return strings.ToLower(string(data[:]))
}

前端列表请求参数示例
在这里插入图片描述

困惑点

刚入门,不知如何写一个公用方法,只需要传入不同的struct则返回不同的结果,这样就避免了多次重复代码,研究中…

好的,以下是使用 Gin 框架编写一个简单的增删改查的示例代码: ```go package main import ( "net/http" "strconv" "github.com/gin-gonic/gin" ) type User struct { ID int `json:"id"` Name string `json:"name"` Age int `json:"age"` } var userList []User func main() { r := gin.Default() // 查询用户列表 r.GET("/users", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "data": userList, }) }) // 根据 ID 查询用户 r.GET("/users/:id", func(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": "Invalid user ID", }) return } for _, user := range userList { if user.ID == id { c.JSON(http.StatusOK, gin.H{ "data": user, }) return } } c.JSON(http.StatusNotFound, gin.H{ "message": "User not found", }) }) // 新增用户 r.POST("/users", func(c *gin.Context) { var user User if err := c.ShouldBindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": "Invalid user data", }) return } user.ID = len(userList) + 1 userList = append(userList, user) c.JSON(http.StatusOK, gin.H{ "message": "User created successfully", "data": user, }) }) // 更新用户 r.PUT("/users/:id", func(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": "Invalid user ID", }) return } var user User if err := c.ShouldBindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": "Invalid user data", }) return } for i, oldUser := range userList { if oldUser.ID == id { user.ID = id userList[i] = user c.JSON(http.StatusOK, gin.H{ "message": "User updated successfully", "data": user, }) return } } c.JSON(http.StatusNotFound, gin.H{ "message": "User not found", }) }) // 删除用户 r.DELETE("/users/:id", func(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "message": "Invalid user ID", }) return } for i, user := range userList { if user.ID == id { userList = append(userList[:i], userList[i+1:]...) c.JSON(http.StatusOK, gin.H{ "message": "User deleted successfully", }) return } } c.JSON(http.StatusNotFound, gin.H{ "message": "User not found", }) }) r.Run() // 启动 HTTP 服务 } ``` 这是一个非常简单的示例,用于演示如何使用 Gin 框架实现增删改查功能。可以通过访问以下 URL 来测试: - 查询用户列表:GET http://localhost:8080/users - 根据 ID 查询用户:GET http://localhost:8080/users/:id - 新增用户:POST http://localhost:8080/users - 更新用户:PUT http://localhost:8080/users/:id - 删除用户:DELETE http://localhost:8080/users/:id 其中,`:id` 代表用户的 ID,需要替换成实际的用户 ID。在请求中,需要提供 JSON 格式的请求体来传递用户数据。可以使用 Postman 等工具来测试这些 API。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值