Go 将无限分类扁平化数据转换为树状结构 ,可用于RBAC权限控制等

作者: 太阳上的雨天 分类: Go 发布时间: 2023-05-23 00:00

案例用到的包

go get github.com/gin-gonic/gin
go get -u gorm.io/gorm
go get gorm.io/driver/mysql

数据库结构

CREATE TABLE `menu` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `pid` int DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `url` varchar(255) DEFAULT NULL,
  `icon` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (1, 0, '系统首页', '', NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (2, 0, '系统管理', NULL, NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (3, 2, '用户管理', NULL, NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (4, 2, '角色管理', NULL, NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (5, 2, '菜单管理', NULL, NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (6, 2, '接口管理', NULL, NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (7, 0, '商品管理', NULL, NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (8, 7, '鞋子管理', NULL, NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (9, 7, '衣服管理', NULL, NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (10, 9, '连衣裙管理', NULL, NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (11, 1, '数据面板', NULL, NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (12, 10, '碎花连衣裙', NULL, NULL);
INSERT INTO `demo`.`menu` (`id`, `pid`, `name`, `url`, `icon`) VALUES (13, 10, '星星连衣裙', NULL, NULL);

main.go

func main() {

    r := gin.Default()

    r.GET("/menu", handler.List)

    r.Run(":9999")

}

go struct 结构

model/menu.go

type Menu struct {
    Id   int    `json:"id"`
    Pid  int    `json:"pid"`
    Name string `json:"name"`
    Url  string `json:"url"`
    Icon string `json:"icon"`
}

用法

handler/menu.go

type TreeList struct {
    model.Menu
    Children []*TreeList
}

func List(c *gin.Context) {

    db := mysql.InitDb()
    menus := make([]*model.Menu, 0)
    db.Find(&menus)

    var nodes []*TreeList
    for _, item := range menus {
        node := &TreeList{
            Menu: model.Menu{
                Id:   item.Id,
                Pid:  item.Pid,
                Name: item.Name,
                Url:  item.Url,
                Icon: item.Icon,
            },
            Children: nil,
        }
        nodes = append(nodes, node)
    }

    treeLists := Tree(nodes, 0)

    c.JSON(http.StatusOK, gin.H{
        "msg":  "success",
        "data": treeLists,
    })
}

func Tree(node []*TreeList, pid int) []*TreeList {
    res := make([]*TreeList, 0)
    for _, v := range node {
        if v.Pid == pid {
            v.Children = Tree(node, v.Id)
            res = append(res, v)
        }
    }
    return res
}

db

func InitDb() *gorm.DB {
    dsn := "root:123456@tcp(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
        SkipDefaultTransaction: false,
        NamingStrategy: schema.NamingStrategy{
            SingularTable: true, 
        },
        Logger:                                   logger.Default.LogMode(logger.Info),
        DisableAutomaticPing:                     false,
        DisableForeignKeyConstraintWhenMigrating: true,
    })
    if err != nil {
        return nil
    }

    return db
}

效果

Localhost:9999/menu

{
    "data":[
        {
            "id":1,
            "pid":0,
            "name":"系统首页",
            "url":"",
            "icon":"",
            "Children":[
                {
                    "id":11,
                    "pid":1,
                    "name":"数据面板",
                    "url":"",
                    "icon":"",
                    "Children":[

                    ]
                }
            ]
        },
        {
            "id":2,
            "pid":0,
            "name":"系统管理",
            "url":"",
            "icon":"",
            "Children":[
                {
                    "id":3,
                    "pid":2,
                    "name":"用户管理",
                    "url":"",
                    "icon":"",
                    "Children":[

                    ]
                },
                {
                    "id":4,
                    "pid":2,
                    "name":"角色管理",
                    "url":"",
                    "icon":"",
                    "Children":[

                    ]
                },
                {
                    "id":5,
                    "pid":2,
                    "name":"菜单管理",
                    "url":"",
                    "icon":"",
                    "Children":[

                    ]
                },
                {
                    "id":6,
                    "pid":2,
                    "name":"接口管理",
                    "url":"",
                    "icon":"",
                    "Children":[

                    ]
                }
            ]
        },
        {
            "id":7,
            "pid":0,
            "name":"商品管理",
            "url":"",
            "icon":"",
            "Children":[
                {
                    "id":8,
                    "pid":7,
                    "name":"鞋子管理",
                    "url":"",
                    "icon":"",
                    "Children":[

                    ]
                },
                {
                    "id":9,
                    "pid":7,
                    "name":"衣服管理",
                    "url":"",
                    "icon":"",
                    "Children":[
                        {
                            "id":10,
                            "pid":9,
                            "name":"连衣裙管理",
                            "url":"",
                            "icon":"",
                            "Children":[
                                {
                                    "id":12,
                                    "pid":10,
                                    "name":"碎花连衣裙",
                                    "url":"",
                                    "icon":"",
                                    "Children":[

                                    ]
                                },
                                {
                                    "id":13,
                                    "pid":10,
                                    "name":"星星连衣裙",
                                    "url":"",
                                    "icon":"",
                                    "Children":[

                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ],
    "msg":"success"
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注