繁体   English   中英

如何在go中使用空结构值制作地图

[英]How to make map with empty struct values in go

如何制作这种结构的地图:


{
    "A": [
        {
            "name": "My name",
            "desc": "aaaa",
            "sub": [] //empty
        },
        {
            "name": "Loc",
            "desc": "bbbb"
            "sub": [
              {
                  "name": "xxxxx",
                  "desc": "aaaa",
              },
              {
                  "name": "yyyyy",
                  "desc": "aaaa",
              },
            ] 
        },
    ],
    "B": [
        {
            "name": "My name b",
            "desc": "cccc",
            "sub": [] //empty
        },
        {
            "name": "tyty",
            "desc": "ffff"
            "sub": [
                {
                    "name": "rrrrrr",
                    "desc": "descrition",
                }
            ] 
        },
    ]
}

我试图这样做,但我不明白。 如何制作空结构/数组以及如何在结构中制作结构?


    type myStruct struct {
        Name string `json:"name"`
        Desc string `json:"desc"`
        // ?? Sub myStruct `json:"sub"`
    }

    m := map[string]interface{}{
        "A": []myStruct{
            {"My name", "aaaa", []???? },
            {"Loc", "bbbb", ??? },
        },
    }

您的原始 JSON 中存在一些拼写错误,但使用JSON-to-Go等在线服务会产生以下结构定义:

type AutoGenerated struct {
    A []struct {
        Name string        `json:"name"`
        Desc string        `json:"desc"`
        Sub  []interface{} `json:"sub"`
    } `json:"A"`
    B []struct {
        Name string        `json:"name"`
        Desc string        `json:"desc"`
        Sub  []interface{} `json:"sub"`
    } `json:"B"`
}

仅供参考,以下是我使用的 JSON 的清理/语法更正版本:

{
    "A": [
        {
            "name": "My name",
            "desc": "aaaa",
            "sub": []
        },
        {
            "name": "Loc",
            "desc": "bbbb",
            "sub": [
              {
                  "name": "xxxxx",
                  "desc": "aaaa"
              },
              {
                  "name": "yyyyy",
                  "desc": "aaaa"
              }
            ]
        }
    ],
    "B": [
        {
            "name": "My name b",
            "desc": "cccc",
            "sub": []
        },
        {
            "name": "tyty",
            "desc": "ffff",
            "sub": [
                {
                    "name": "rrrrrr",
                    "desc": "descrition"
                }
            ] 
        }
    ]
}

您可以使用以下有效的结构类型定义。 它避免了不方便用于访问数据的interface{} 根据您的喜好更改类名称。

package main

import (
    "fmt"
    "encoding/json"
)

var str = `{
    "A": [
        {
            "name": "My name",
            "desc": "aaaa",
            "sub": []
        },
        {
            "name": "Loc",
            "desc": "bbbb",
            "sub": [
              {
                  "name": "xxxxx",
                  "desc": "aaaa"
              },
              {
                  "name": "yyyyy",
                  "desc": "aaaa"
              }
            ]
        }
    ],
    "B": [
        {
            "name": "My name b",
            "desc": "cccc",
            "sub": []
        },
        {
            "name": "tyty",
            "desc": "ffff",
            "sub": [
                {
                    "name": "rrrrrr",
                    "desc": "descrition"
                }
            ] 
        }
    ]
}`

// DescLeaf is leaf of description tree
type DescLeaf struct {
    Name string `json:"name"`
    Desc string `json:"desc"`
}

// DescNode is node of description tree
type DescNode struct {
    Name string `json:"name"`
    Desc string `json:"desc"`
    Sub []DescLeaf `json:"sub"` 
}

// DescRoot is root of description tree
type DescRoot struct {
    A []DescNode `json:"A"`
    B []DescNode `json:"B"`
}

func main() {
    var r DescRoot

    err := json.Unmarshal([]byte(str), &r)
    if err != nil {
        fmt.Println("error:", err)
    } else {
        fmt.Println("done:", r)
    }
}

产出

done: {[{My name aaaa []} {Loc bbbb [{xxxxx aaaa} {yyyyy aaaa}]}] [{My name b cccc []} {tyty ffff [{rrrrrr descrition}]}]}

根据示例 JSON,您似乎正在尝试创建递归 JSON 结构。 递归 JSON(和递归结构)都非常有用,但您必须确保正确构建它们,否则您可能会遇到无法在内存中创建结构的情况。

让我们举一个简单的例子:

type example struct {
    itemOne int64
    subElement example
}

当程序开始在内存中创建结构时,它需要弄清楚它需要多大。 这个过程是这样的:

  1. 计算出 itemOne 的大小。
    • 向分配空间添加 8 个字节。 (总计:8)
  2. 弄清楚制作子元素有多大。
    1. 弄清楚使 subElement-itemOne 有多大
      • 向分配空间添加 8 个字节。 (总计:16)
    2. 计算出 subElement-subElement 有多大
      1. 等等

这个过程将永远持续下去,直到 1:计算内存大小的程序发生堆栈溢出,或 2:程序所需的总内存太大。

在 Go 的情况下,这种情况实际上已经专门内置了检测,所以第二步实际上永远不会运行。 返回./prog.go:7:6: invalid recursive type example示例。

这个问题的解决方案是创建一个结构,其中计算器知道它必须添加到结构中的所有内容的确切大小。 为此,我们利用了这样一个事实,即所有结构都具有指向它们在内存中的位置的指针的大小。

type example struct {
    itemOne int64
    subElement *example
}

添加那个星号使得之前的递归过程是有限的。

  1. 计算出 itemOne 的大小。
    • 向分配空间添加 8 个字节。 (总计:8)
  2. 弄清楚使 subElement指针有多大。
    • 向分配空间添加 8 个字节(共 16 个)
  3. 清理并分配 16 个字节。

然后将这些值设置为其默认值。 整数设置为零,并指向 nil 值(也为零)。 将其中之一传递到 json unmarshal 将创建您正在寻找的确切结构。

type sub struct {
    Name string     `json:"name"`
    Desc string     `json:"desc"`
    Sub  []*sub     `json:"sub"`
}

完整示例(感谢 chmike 为该示例完成了大部分繁重的工作/格式化)

如果你想深入研究 golang 和指针,可以在网上找到大量资源,例如官方文档,其中包含一些信息,或者更侧重于示例的geeksforgeeks 请注意golang 的自动取消引用

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM