### **goshop开源项目的更新**
>备注:前面项目中用到的代码已经分享到`GitHub`中去了,并且以后所有项目中会出现的代码都会提交上去,欢迎查阅。
> 地址 [`goshop`](https://gitee.com/jobhandsome/goshop/) 感兴趣的可以点个`star`哦~ [`goshop开源项目的更新` ](https://gitee.com/jobhandsome/goshop/)
#### **今天咱们做一个`无限级结构树形数据格式`:**
1. **做一个菜单列表形式的一个树形结构,以满足后续的功能业务开发,类似于下图的功能**
![image.png](https://static.golangjob.cn/220430/32ab8fdc438fe082b729edd3e6c96fd0.png)
2. **做成方便扩展的方式**
****
#### **接下来咱们就来实现以上的问题和功能:**
* **先修改一下分页获取全部数据的方法 `findAll`,将之前`[]Roles`改为`[]*Roles`,如果这里不明白的话,请看之前的的文章:
[`Go项目实战之开发完善分页插件(易扩展方式)-------【goshop开源项目】【第12次更新】`](https://studygolang.com/topics/15435)**
```go
// 根据检索条件,获取记录行,并获取总记录条数
func (Roles) FindAll(DB *gorm.DB, params map[string]interface{}) ([]*Roles, int64) {
var GoodResult []*Roles
page := params["page"].(string) // 对返回的interface类型进行转换成字符串
pageSize := params["pageSize"].(string) // 对返回的interface类型进行转换成字符串
// 这里使用了过滤,在下面使用Where条件时过滤掉page,pageSize
ParamsFilter := utils.ParamsFilter(params, "page,pageSize")
// 通过 Scopes 引用加载 分页类中返回的 DB指针
DB.Scopes(Paginate.Paginate(page, pageSize)).Where(ParamsFilter).Order("created_at desc").Find(&Result)
// 这里时查询全部数据,用于返回总记录条数
TotalCount := DB.Find(&Goods{})
return Result, TotalCount.RowsAffected
}
// 这是过滤的封装,一起贴出来了
func ParamsFilter(params map[string]interface{}, isFilterStr string) map[string]interface{} {
var data = make(map[string]interface{})
for key, value := range params {
if find := strings.Contains(isFilterStr, key); !find {
data[key] = value
}
}
return data
}
```
* **接下来就是重头戏了,将查询出来的`[]*Roles` 结构体数据,处理成咱们预想的数据格式**
```go
// 对应的数据结构体
type Roles struct {
Model
Name string `json:"name" gorm:"size:100;index;default:'';not null;"` // 角色名称
Alias string `json:"alias" grom:"size:255;index;default:'';not nill;"` // 别名
ParentID uint `json:"parent_id" gorm:"size:10;index;default:0;not null;"` // 父级ID
Sort uint `json:"sort" gorm:"size:1;index;default:0;"` // 排序值
Remark string `json:"remark" gorm:"size:255;"` // 备注
Status uint `json:"status" gorm:"size:1;index;default:0;"` // 状态(1:启用 2:禁用)
Children *RoleTrees `json:"children"` // 这里是最关键的一步
}
// RoleTrees 二叉树列表
type RoleTrees []*Roles
// ToTree 转换为树形结构
func (Roles) ToTree(data RoleTrees) RoleTrees {
// 定义 HashMap 的变量,并初始化
TreeData := make(map[uint]*Roles)
// 先重组数据:以数据的ID作为外层的key编号,以便下面进行子树的数据组合
for _, item := range data {
TreeData[item.ID] = item
}
// 定义 RoleTrees 结构体
var TreeDataList RoleTrees
// 开始生成树形
for _, item := range TreeData {
// 如果没有根节点树,则为根节点
if item.ParentID == 0 {
// 追加到 TreeDataList 结构体中
TreeDataList = append(TreeDataList, item)
// 跳过该次循环
continue
}
// 通过 上面的 TreeData HashMap的组合,进行判断是否存在根节点
// 如果存在根节点,则对应该节点进行处理
if p_item, ok := TreeData[item.ParentID]; ok {
// 判断当次循环是否存在子节点,如果没有则作为子节点进行组合
if p_item.Children == nil {
// 写入子节点
children := RoleTrees{item}
// 插入到 当次结构体的子节点字段中,以指针的方式
p_item.Children = &children
// 跳过当前循环
continue
}
// 以指针地址的形式进行追加到结构体中
*p_item.Children = append(*p_item.Children, item)
}
}
return TreeDataList
}
```
* **到这里逻辑代码已经全部完成了,但是如何使用呢? 下面咱们就来说一下如何使用?在`controller`中进行调用:**
```go
// 查询数据
var roles model.Roles
Result, totalCount := roles.FindAll(DB, params)
TreeResult := roles.ToTree(Result)
```
### **走到这里就实现了`无限级结构树形数据格式`~~~**
### **更多功能请持续关注!!!!! **
### **欢迎各位加我的微信(`jobhandsome`)跟我一起完成并推动项目的发展!**
![加入我们.png](https://static.golangjob.cn/220428/76016202be4db073f7b6c7598e4f1f26.png)
有疑问加站长微信联系(非本文作者)
![](https://static.golangjob.cn/static/img/footer.png?imageView2/2/w/280)