You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go语言中构造指定嵌套树形结构并从数据库表加载对应数据

Go构造嵌套树形结构的实现方案

不要使用多层嵌套map实现递归树形结构,这种方式灵活性差、维护难度高,推荐使用递归结构体实现,具体方案如下:


1. 定义递归节点结构体

首先定义递归结构对应树形节点,和目标JSON结构字段一一对应:

type TreeNode struct {
    UUID     string      `json:"uuid"`
    Label    string      `json:"label"`
    Children []*TreeNode `json:"children,omitempty"` // 无孩子节点时序列化自动忽略该字段
}

2. 核心实现逻辑

你的数据库行存储的是叶子节点到根节点的路径:level4对应根节点label、level3对应二级节点label、level2对应三级节点label、level1对应叶子节点label,仅叶子节点的uuid直接从数据库取,上层节点的uuid可根据业务规则生成。

我们通过缓存已创建的节点避免重复构建,逐层挂载节点到对应父节点的children数组中即可。

3. 完整可运行代码示例

package main

import (
	"encoding/json"
	"fmt"
)

// DbRow 对应数据库查询返回的每行数据结构
type DbRow struct {
	Uuid   string
	Level1 string // 叶子节点label
	Level2 string // 三级节点label
	Level3 string // 二级节点label
	Level4 string // 根节点label
}

// TreeNode 树形节点结构
type TreeNode struct {
	UUID     string      `json:"uuid"`
	Label    string      `json:"label"`
	Children []*TreeNode `json:"children,omitempty"`
}

func main() {
	// 模拟从数据库读取的示例数据
	rows := []DbRow{
		{Uuid: "uuid5", Level1: "label5", Level2: "label3", Level3: "label2", Level4: "label1"},
		{Uuid: "uuid7", Level1: "label7", Level2: "label3", Level3: "label2", Level4: "label1"},
		{Uuid: "uuid6", Level1: "label6", Level2: "label4", Level3: "label2", Level4: "label1"},
	}

	// 缓存已创建的节点,key为 层级+label 避免不同层级同label重复,value为节点指针
	nodeCache := make(map[string]*TreeNode)
	var root *TreeNode

	for _, row := range rows {
		// 按根到叶子的路径顺序处理
		path := []string{row.Level4, row.Level3, row.Level2, row.Level1}
		var currentParent *TreeNode

		for level, label := range path {
			// 构造缓存key,层级+label唯一标识节点
			cacheKey := fmt.Sprintf("%d_%s", level, label)
			// 节点已存在直接跳过创建
			if node, ok := nodeCache[cacheKey]; ok {
				currentParent = node
				continue
			}

			// 创建新节点
			newNode := &TreeNode{Label: label}
			// 叶子节点用数据库返回的uuid,上层节点按业务规则生成uuid
			if level == len(path)-1 {
				newNode.UUID = row.Uuid
			} else {
				// 可替换为你实际的上层节点uuid生成逻辑,这里为匹配示例用固定规则生成
				newNode.UUID = fmt.Sprintf("uuid%d", level+1)
			}
			nodeCache[cacheKey] = newNode

			// 挂载节点到父节点
			if currentParent == nil {
				root = newNode
			} else {
				currentParent.Children = append(currentParent.Children, newNode)
			}
			currentParent = newNode
		}
	}

	// 序列化输出验证结果
	jsonRes, err := json.MarshalIndent(root, "", "  ")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(jsonRes))
}

代码运行后输出的JSON结构完全匹配你给出的目标格式,如果你需要调整上层节点的uuid生成规则,直接修改对应代码块即可。如果存在同层级label重复的场景,也可以调整缓存key的生成规则适配你的业务。

内容的提问来源于stack exchange,提问作者cnknob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 12:24:02