Golang中如何创建嵌套结构体

Golang中如何创建嵌套结构体 我想创建一个嵌套结构体。我不知道子对象的深度。

示例:我想在运行时创建菜单,子菜单数量没有限制。

示例 根节点 M1 M11 M111 M12 M121 M2 M21 M211 M2111 M212 M2121 M3 M4

如何实现这个功能

9 回复

是的。如果你能提供帮助,那就太好了。

更多关于Golang中如何创建嵌套结构体的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,我知道,但如何深入到子层级。

听起来你可能是在问关于递归的问题:

https://gobyexample.com/recursion

在这种情况下,递归地遍历你的 Menu.Items.Children

我知道必须使用递归,但我的问题是

menu[0].item[0] 我该如何以编程方式实现它

我可以定义最多 5 个层级

不太清楚您具体想要什么,但我觉得可能是类似这样的结构:

type MenuItem struct {
  ID int
  Title string
  Children []*MenuItem
}

type Menu struct {
  ID int
  Title string
  Items []*MenuItem
}

packs: 我知道我必须使用递归,但我的问题是 menu[0].item[0] 我该如何通过编程方式实现它

这……在我看来不是一个问题。你是在问如何创建/定义你的结构体吗?还是在问如何索引到子项?只要你是在递归地显示它们,那么你有多少层级都无关紧要。

在数据表中,应该存在价格和图标字段吗?我的意思是,原始的数据表结构是:

type MenuItem struct {
  Id string
  ParentId string
  Name string
  Price float64
  Icon string 
}

如果是这样,那么你只需要在该结构体中添加一个 items 切片:

type MenuItem struct {
  Id string
  ParentId string
  Name string
  Price float64
  Icon string 
  Items []MenuItem
}

有些条目没有价格和图标(上层父节点),因此你可以在结构体上添加一些标签:

type MenuItem struct {
  Id       string `json:"id,omitempty"`
  ParentId string `json:"-"`
  Name     string     `json:"name,omitempty"`
  Price    float64    `json:"price,omitempty"`
  Icon     string     `json:"icon,omitempty"`
  Items    []MenuItem `json:"items,omitempty"`
}

现在你需要一个函数,该函数返回给定 id 对应的 items 切片,如果该条目没有子项,则返回一个空切片。

func setChildren(menuItems []MenuItem, parentId string) []MenuItem) {
   result := make([]MenuItem,0)
   for _, mi := range menuItems {
      if mi.ParentId == parentId {
        result = append(result, mi)
      }	  
    }

    return result
}

希望对你有帮助!!!

你好,

我有以下表格。

myid parentid menu_name 1 0 Video Players 2 0 Televisions 11 1 HD Video Player 12 1 CD player 13 1 USB player 21 2 SuperLCD 42 22 2 SuperLED 42 23 2 SuperLED 50 24 2 SuperLCD 55 (Not available) 25 2 SuperLCD 70 111 11 Video1 112 11 Video2 1111 111 Video111 1112 111 Video112

我想要这种类型的JSON对象

[{
  id: '1',
  name: 'Video Players',
  items: [{
    id: '1_1',
    name: 'HD Video Player',
    price: 220,
    icon: 'images/products/1.png',
  }, {
    id: '1_2',
    name: 'SuperHD Video Player',
    icon: 'images/products/2.png',
    price: 270,
  }],
}, {
  id: '2',
  name: 'Televisions',
  items: [{
    id: '2_1',
    name: 'SuperLCD 42',
    icon: 'images/products/7.png',
    price: 1200,
  }, {
    id: '2_2',
    name: 'SuperLED 42',
    icon: 'images/products/5.png',
    price: 1450,
  }, {
    id: '2_3',
    name: 'SuperLED 50',
    icon: 'images/products/4.png',
    price: 1600,
  }, {
    id: '2_4',
    name: 'SuperLCD 55 (Not available)',
    icon: 'images/products/6.png',
    price: 1350,
    disabled: true,
  }, {
    id: '2_5',
    name: 'SuperLCD 70',
    icon: 'images/products/9.png',
    price: 4000,
  }],
}, {
  id: '3',
  name: 'Monitors',
  items: [{
    id: '3_1',
    name: '19"',
    items: [{
      id: '3_1_1',
      name: 'DesktopLCD 19',
      icon: 'images/products/10.png',
      price: 160,
    }],
  }, {
    id: '3_2',
    name: '21"',
    items: [{
      id: '3_2_1',
      name: 'DesktopLCD 21',
      icon: 'images/products/12.png',
      price: 170,
    }, {
      id: '3_2_2',
      name: 'DesktopLED 21',
      icon: 'images/products/13.png',
      price: 175,
    }],
  }],
}, {
  id: '4',
  name: 'Projectors',
  items: [{
    id: '4_1',
    name: 'Projector Plus',
    icon: 'images/products/14.png',
    price: 550,
  }, {
    id: '4_2',
    name: 'Projector PlusHD',
    icon: 'images/products/15.png',
    price: 750,
  }],
}]

我已经尝试了所有选项。我无法在运行时创建包含这些字段的数组。

在Go中可以通过递归结构体实现嵌套结构体,深度不受限制。这里给出两种常见实现方式:

方法1:使用指针切片实现树形结构

type MenuItem struct {
    Name     string
    Children []*MenuItem
}

// 创建示例菜单
func createMenu() *MenuItem {
    root := &MenuItem{Name: "根节点"}
    
    m1 := &MenuItem{Name: "M1"}
    m11 := &MenuItem{Name: "M11"}
    m111 := &MenuItem{Name: "M111"}
    m12 := &MenuItem{Name: "M12"}
    m121 := &MenuItem{Name: "M121"}
    
    m11.Children = []*MenuItem{m111}
    m1.Children = []*MenuItem{m11, m12}
    m12.Children = []*MenuItem{m121}
    
    m2 := &MenuItem{Name: "M2"}
    m21 := &MenuItem{Name: "M21"}
    m211 := &MenuItem{Name: "M211"}
    m2111 := &MenuItem{Name: "M2111"}
    m212 := &MenuItem{Name: "M212"}
    m2121 := &MenuItem{Name: "M2121"}
    
    m211.Children = []*MenuItem{m2111}
    m21.Children = []*MenuItem{m211, m212}
    m212.Children = []*MenuItem{m2121}
    m2.Children = []*MenuItem{m21}
    
    root.Children = []*MenuItem{m1, m2, 
        &MenuItem{Name: "M3"}, 
        &MenuItem{Name: "M4"}}
    
    return root
}

// 遍历菜单
func printMenu(menu *MenuItem, depth int) {
    indent := strings.Repeat("  ", depth)
    fmt.Printf("%s%s\n", indent, menu.Name)
    for _, child := range menu.Children {
        printMenu(child, depth+1)
    }
}

方法2:运行时动态构建嵌套结构

type DynamicMenu struct {
    Name     string
    Children []DynamicMenu
}

// 运行时添加子菜单
func (m *DynamicMenu) AddChild(name string) *DynamicMenu {
    child := DynamicMenu{Name: name}
    m.Children = append(m.Children, child)
    return &m.Children[len(m.Children)-1]
}

// 使用示例
func buildMenuDynamically() DynamicMenu {
    root := DynamicMenu{Name: "根节点"}
    
    m1 := root.AddChild("M1")
    m11 := m1.AddChild("M11")
    m11.AddChild("M111")
    m12 := m1.AddChild("M12")
    m12.AddChild("M121")
    
    m2 := root.AddChild("M2")
    m21 := m2.AddChild("M21")
    m211 := m21.AddChild("M211")
    m211.AddChild("M2111")
    m212 := m21.AddChild("M212")
    m212.AddChild("M2121")
    
    root.AddChild("M3")
    root.AddChild("M4")
    
    return root
}

// 查找并添加子菜单
func (m *DynamicMenu) FindAndAdd(parentName, childName string) bool {
    if m.Name == parentName {
        m.AddChild(childName)
        return true
    }
    
    for i := range m.Children {
        if m.Children[i].FindAndAdd(parentName, childName) {
            return true
        }
    }
    return false
}

方法3:使用map实现快速查找

type MenuNode struct {
    ID       string
    Name     string
    Children map[string]*MenuNode
}

func NewMenuNode(id, name string) *MenuNode {
    return &MenuNode{
        ID:       id,
        Name:     name,
        Children: make(map[string]*MenuNode),
    }
}

func (m *MenuNode) AddChild(id, name string) *MenuNode {
    child := NewMenuNode(id, name)
    m.Children[id] = child
    return child
}

// 构建示例菜单
func buildMenuWithMap() *MenuNode {
    root := NewMenuNode("root", "根节点")
    
    m1 := root.AddChild("m1", "M1")
    m11 := m1.AddChild("m11", "M11")
    m11.AddChild("m111", "M111")
    m12 := m1.AddChild("m12", "M12")
    m12.AddChild("m121", "M121")
    
    return root
}

JSON序列化示例

type Menu struct {
    Title    string  `json:"title"`
    Children []Menu  `json:"children,omitempty"`
}

func createJSONMenu() Menu {
    return Menu{
        Title: "根节点",
        Children: []Menu{
            {
                Title: "M1",
                Children: []Menu{
                    {
                        Title: "M11",
                        Children: []Menu{
                            {Title: "M111"},
                        },
                    },
                    {
                        Title: "M12",
                        Children: []Menu{
                            {Title: "M121"},
                        },
                    },
                },
            },
            {Title: "M2"},
            {Title: "M3"},
            {Title: "M4"},
        },
    }
}

// 转换为JSON
func menuToJSON() string {
    menu := createJSONMenu()
    data, _ := json.MarshalIndent(menu, "", "  ")
    return string(data)
}

这些实现方式都支持无限深度嵌套,可以根据具体需求选择使用切片、map或直接递归结构体。方法1和方法2更接近传统的树形结构,方法3适合需要快速查找节点的场景。

回到顶部