您的位置:首页 > 娱乐 > 八卦 > golang无限层级菜单,子菜单Children 数据递归处理和gorm数据获取示例

golang无限层级菜单,子菜单Children 数据递归处理和gorm数据获取示例

2024/12/28 4:10:14 来源:https://blog.csdn.net/tekin_cn/article/details/140457035  浏览:    关键词:golang无限层级菜单,子菜单Children 数据递归处理和gorm数据获取示例

golang中处理带层级的菜单时我们可以有多重方法, 对于数据量大的,我们可以使用pid先通过sql查询不同层级的菜单,然后在拼接为我们需要的菜单,  不过这样做的话对于数据库的压力会大一些,一般不推荐使用因为数据库的资源是比较宝贵的。 我们一般采用先把相关的数据都一次性拉出来后再使用递归的方式对数据进行二次处理,这样可大大的减轻数据库的压力。

带层级子菜单Children菜单数据 gorm获取和递归处理示例

gorm菜单表实体模型定义

// model.SysMenu 菜单表gorm实体模型定义 示例
type SysMenu struct {ID        uint           `gorm:"primaryKey"`Pid    int64     `gorm:"column:pid;type:bigint(20);comment:父菜单ID" json:"pid"`  // 父菜单IDName   string    `gorm:"column:name;type:varchar(50);not null;comment:菜单名称" json:"name"`  // 菜单名称CreatedAt time.TimeUpdatedAt time.TimeDeletedAt gorm.DeletedAt `gorm:"index"`
}// TableName SysMenu's table name
func (*SysMenu) TableName() string {return "sys_menu"
}

展现给用户的的带子菜单的层级菜单模型定义

// 这个是我们返回前端的带层级的菜单对象
type SysMenuExtend struct {model.SysMenu // 继承model.SysMenu实体模型Children   []*SysMenuExtend `gorm:"-" json:"children,omitempty"` // 子菜单 注意如果我们需要直接使用SysMenuExtend通过gorm从数据库中获取数据集,这这里必须使用gorm:"-"忽略这个字段,否则读取数据会报错
}

层级菜单gorm数据获取和递归处理示例


var MenuSvc = &menuSvc{}type menuSvc struct {
}
// 根据用户ID读取菜单数据
func (s *menuSvc) GetMenusByUid(c *ginx.XContext, uid int32, router ...bool) ([]*model.SysMenuExtend, error) {//从数据库中读取list, err := s.getMenusListByUid(c, uid)if err != nil {return nil, err}result := s.handleMenusExtend(c, list, 0)return result, nil
}// 根据用户id获取用户的全部菜单
func (s *menuSvc) getMenusListByUid(c *ginx.XContext, uid int32) ([]*model.SysMenuExtend, error) {var list []*model.SysMenuExtend// gorm可直接通过Table方法获取表对象,这里 m表示给表起别名m := global.Db.Table("sys_menu m")m = m.Select("distinct m.id, m.pid, m.name, ifnull(m.perms,'') as perms")m = m.Joins("LEFT JOIN sys_role_menu rm on rm.menu_id = m.id")m = m.Joins("LEFT JOIN sys_user_role ur on ur.role_id = rm.role_id ")m = m.Where("ur.uid = ? ", uid)m = m.Order("m.pid asc")if err := m.Find(&list).Error; err != nil {return nil, myerror.New("读取数据失败")}return list, nil
}// 带层级菜单 gorm子菜单Children 数据递归处理和获取
// 这里的 menus是所有的menu数据, pid为父级ID,
func (s *menuSvc) handleMenusExtend(c *ginx.XContext, menus []*SysMenuExtend, pid int64) []*SysMenuExtend {var result []*SysMenuExtendfor _, menu := range menus {if menu.Pid == pid {s.recursionFn(c, menus, menu) // 调用递归方法递归处理result = append(result, menu)}}return result
}// 递归处理
func (s *menuSvc) recursionFn(c *ginx.XContext, menus []*SysMenuExtend, entity *SysMenuExtend) {childMenus := s.getChildList(c, menus, entity)entity.Children = childMenusfor _, childMenu := range childMenus {if s.hasChild(c, menus, childMenu) {for _, menu := range childMenus {s.recursionFn(c, menus, menu)}}}
}// 获取子级列表
func (s *menuSvc) getChildList(c *ginx.XContext, menus []*SysMenuExtend, sysMenuExtend *SysMenuExtend) []*SysMenuExtend {var tlist []*SysMenuExtendfor _, menu := range menus {if menu.Pid == sysMenuExtend.ID {tlist = append(tlist, menu)}}return tlist
}// 判断是是否还有子级
func (s *menuSvc) hasChild(c *ginx.XContext, menus []*SysMenuExtend, entity *SysMenuExtend) bool {return len(s.getChildList(c, menus, entity)) > 0
}

上面的 global.Db 这个是你自己定义的gorm全局数据库的链接对象*gorm.DB

总结

我们通过递归处理方法来对菜单进行二次处理,这样避免了多次查询数据库,这样可大大提高我们网站的性能。通过使用递归函数,我们可以处理无限层级的菜单, 如果是直接查询数据库方式的话无限层级的菜单,每层你就要查询一次数据库这个很容易数据库就挂掉。

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com