新手参照 gorm 写的带模型关联的用户分页数据接口,求帮优化下
这几天上班没事做,看了下GO语言,试着写了下用户的分页接口,求指点优化下:
routers:
user := router.Group("user")
{
user.GET("/", controllers.UserIndex) // 是这个
user.GET("/:id", controllers.UserShow)
user.POST("/", controllers.UserStore)
user.PUT("/:id", controllers.UserUpdate)
user.DELETE("/:id", controllers.UserDestroy)
}
controlers:
package controllers
import (
"TongJiHouTai/gin/models"
"github.com/gin-gonic/gin"
"net/http"
"strconv"
"time"
)
func UserIndex(c *gin.Context) {
phone := c.Query("phone")
size, err := strconv.Atoi(c.DefaultQuery("size", "10"))
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": 500,
"message": err.Error(),
})
return
}
var u models.User
count := u.Count()
var search models.UserSearch
search.Page = page
search.Size = size
search.Phone = phone
users, err := u.Page(search)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": 500,
"message": err.Error(),
})
return
}
var response PageResponse
response.Code = 0
response.Message = "success"
response.Data = users
response.Total = count
response.PerPage = size
response.CurrentPage = page
response.TotalPage = (count + size - 1) / size
c.JSON(http.StatusOK, response)
}
models:
package models
import (
"TongJiHouTai/gin/databases"
"database/sql"
"fmt"
"time"
)
//首字母大写则该成员为公有成员(对外可见),否则是私有成员(对外不可见)
type User struct {
Id int `gorm:"column:id; primary_key" json:"id"`
Name string `gorm:"column:name" json:"name"`
Pid *int `gorm:"column:pid" json:"-"` // * 可匹配null
Phone string `gorm:"column:phone" json:"phone"`
Password string `gorm:"column:password" json:"-"` // - 表示输出json结果隐藏此字段
Cid *string `gorm:"column:cid" json:"cid" json:"-"`
IsRoot int `gorm:"column:is_root" json:"is_root"`
LastLoginTime *time.Time `gorm:"column:last_login_time" json:"-"`
LastLogoutTime *time.Time `gorm:"column:last_logout_time" json:"-"`
CreatedAt *time.Time `gorm:"column:created_at" json:"created_at"`
UpdatedAt *time.Time `gorm:"column:updated_at" json:"-"`
DeletedAt *time.Time `gorm:"column:deleted_at" json:"-"` // - 表示输出json结果隐藏此字段
Cids []Cid `json:"cids" gorm:"many2many:user_cids;ForeignKey:id;AssociationForeignKey:id"` // 多对多
Roles []Role `json:"roles" gorm:"many2many:user_roles;ForeignKey:id;AssociationForeignKey:id"` // 多对多
Children []User `json:"children" gorm:"ForeignKey:pid;AssociationForeignKey:id"` // 1对多
Parent *User `json:"parent" gorm:"ForeignKey:id;AssociationForeignKey:pid"` // 多对1
}
type JwtToken struct {
Token string `json:"token"`
}
type UserSearch struct {
Page int `json:"page"`
Size int `json:"size"`
Phone string `json:"phone"`
}
// 设置表名
func (User) TableName() string {
return "users"
}
func (u *User) Page(search UserSearch) ([]*User, error) {
var rows *sql.Rows
query := databases.DB.Table("users").Debug()
if search.Page > 0 {
query = query.Order("id desc").Offset((search.Page - 1) * search.Size).Limit(search.Size)
if search.Phone != "" {
query = query.Where("phone LIKE ?", "%"+search.Phone+"%")
}
} else {
query = query.Order("id desc")
if search.Phone != "" {
query = query.Where("phone LIKE ?", "%"+search.Phone+"%")
}
}
rows, err := query.Rows()
if err != nil {
return nil, err
}
defer rows.Close()
users := make([]*User, 0)
for rows.Next() {
var user User
_ = databases.DB.ScanRows(rows, &user)
query := databases.DB.Model(&user).Debug().
Related(&user.Cids, "Cids").
Related(&user.Roles, "Roles")
if user.Pid != nil {
query = query.Preload("Parent")
} else {
query = query.Preload("Children")
}
query = query.First(&user)
users = append(users, &user)
}
return users, nil
}
返回结果:
{
"code": 0,
"message": "success",
"data": [
{
"id": 38,
"name": "测试修改",
"phone": "13137284666",
"cid": null,
"is_root": 0,
"created_at": "2020-01-09T16:51:56+08:00",
"cids": [],
"roles": [
{
"id": 2,
"name": "普通用户",
"created_at": "2019-10-25T16:38:23+08:00",
"updated_at": "2019-10-25T16:38:23+08:00",
"users": null,
"permissions": null
}
],
"children": null,
"parent": {
"id": 29,
"name": "用户1",
"phone": "13437284998",
"cid": null,
"is_root": 1,
"created_at": "2019-10-29T09:59:16+08:00",
"cids": null,
"roles": null,
"children": null,
"parent": null
}
},
{
"id": 35,
"name": "kll",
"phone": "17354306026",
"cid": null,
"is_root": 1,
"created_at": "2020-01-08T15:17:40+08:00",
"cids": [
{
"id": 47,
"cid": "10030",
"user_id": 0,
"agent_name": "周万林",
"province": "湖北省",
"city": "荆州市",
"promoter": "刘超俊",
"remark": "",
"created_at": "2019-10-29T12:21:17+08:00",
"updated_at": "2019-10-29T12:21:17+08:00",
"users": null,
"products": null
},
{
"id": 48,
"cid": "10031",
"user_id": 0,
"agent_name": "XX欢",
"province": "江苏省",
"city": "苏州市",
"promoter": "XX钰",
"remark": "",
"created_at": "2019-10-29T12:22:02+08:00",
"updated_at": "2019-11-01T14:33:43+08:00",
"users": null,
"products": null
}
],
"roles": [
{
"id": 1,
"name": "超级管理员",
"created_at": "2019-10-25T16:38:23+08:00",
"updated_at": "2019-10-25T16:38:23+08:00",
"users": null,
"permissions": null
}
],
"children": [],
"parent": null
},
{
"id": 34,
"name": "wew",
"phone": "wew",
"cid": null,
"is_root": 1,
"created_at": "2020-01-03T16:27:18+08:00",
"cids": [
{
"id": 79,
"cid": "ABCD1234",
"user_id": 0,
"agent_name": "hwt2",
"province": "XXX",
"city": "XX市",
"promoter": "XX涛",
"remark": "2",
"created_at": "2020-04-17T14:39:53+08:00",
"updated_at": "2020-04-17T14:39:53+08:00",
"users": null,
"products": null
},
{
"id": 46,
"cid": "10029",
"user_id": 0,
"agent_name": "侯蒙",
"province": "安徽省",
"city": "阜阳市",
"promoter": "张雅静",
"remark": "",
"created_at": "2019-10-29T12:20:43+08:00",
"updated_at": "2019-10-29T12:20:43+08:00",
"users": null,
"products": null
}
],
"roles": [
{
"id": 3,
"name": "数据查看",
"created_at": "2019-10-25T16:48:48+08:00",
"updated_at": "2019-10-25T16:48:48+08:00",
"users": null,
"permissions": null
},
{
"id": 11,
"name": "代理商",
"created_at": "2020-01-09T17:23:53+08:00",
"updated_at": "2020-01-09T17:23:53+08:00",
"users": null,
"permissions": null
}
],
"children": [
{
"id": 61,
"name": "1232",
"phone": "123",
"cid": "1000111",
"is_root": 0,
"created_at": "2020-01-18T18:45:12+08:00",
"cids": null,
"roles": null,
"children": null,
"parent": null
},
{
"id": 66,
"name": "33",
"phone": "13554204137",
"cid": null,
"is_root": 0,
"created_at": "2020-04-17T12:10:05+08:00",
"cids": null,
"roles": null,
"children": null,
"parent": null
}
],
"parent": null
}
],
"total": 40,
"per_page": 3,
"current_page": 10,
"total_page": 14
}
返回的结果隐藏了 password 等字段
users 多对多 roles
users 多对多 cids
users 一对多 自己的 children
users 多对一 自己的 parent
勿笑,新手参照gorm写的,总觉得那个for里面被我写了sql有点不好,求帮优化下
10条分页数据查询出来后, 根据id去查询对应
roles/cids
, 再在for
循环中匹配关联的数据, 写法上会分离点, 但是能避免for
循环内的循环数据库操作.@taadis 不是很明白,我去看看日志打印了几条数据先
@taadis 在for之前拿的到每条user的id吗?感觉拿不到吧
...你 for 之前查询出来的 rows 是啥数据?
@taadis rows也得遍历才能拿到具体的单个id吧,总感觉你说的那样不行,下周我试试你说的
单一职责原则,分页应该只包含分页逻辑,将关联查询单独分离成方法,接受者为
*user
,返回[]user
, 降低耦合,方便复用