【问题标题】:How to make map with empty struct values in go如何在go中使用空结构值制作地图
【发布时间】:2020-01-21 14:28:55
【问题描述】:

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


{
    "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",
                }
            ] 
        },
    ]
}

我试图这样做,但我没有得到它。如何制作空结构/数组以及如何在结构中制作结构?

键入 myStruct 结构 { 名称字符串`json:"name"` 描述字符串`json:"desc"` // ??子 myStruct `json:"sub"` } m := 地图[字符串]接口{}{ “A”:[]myStruct{ {“我的名字”,“aaaa”,[]??? }, {“Loc”,“bbbb”,??? }, }, }

【问题讨论】:

  • 使用指针:Sub *myStruct.
  • Sub 字段是表示零还是一myStructs?或零,一个或多个?如果为零或一,则 @BurakSerdar 建议有效。如果不止一个,则使用切片。

标签: dictionary go struct


【解决方案1】:

您的原始 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"
                }
            ] 
        }
    ]
}

【讨论】:

    【解决方案2】:

    您可以使用以下结构类型定义。它避免了使用不方便访问数据的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}]}]}
    

    【讨论】:

      【解决方案3】:

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

      我们举个简单的例子:

      type example struct {
          itemOne int64
          subElement example
      }
      

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

      1. 计算出 itemOne 的大小。
        • 向分配空间添加 8 个字节。 (共:8 个)
      2. 计算子元素的大小。
        1. 弄清楚子元素项的大小
          • 向分配空间添加 8 个字节。 (共:16 个)
        2. 弄清楚子元素的大小

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

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

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

      type example struct {
          itemOne int64
          subElement *example
      }
      

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

      1. 计算出 itemOne 的大小。
        • 向分配空间添加 8 个字节。 (共:8 个)
      2. 计算子元素指针的大小。
        • 分配空间增加 8 个字节(共 16 个)
      3. 清理并分配 16 个字节。

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

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

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

      如果您想深入研究 golang 和指针,网上有很多资源,例如 official documentation,其中有一些信息散布在各处,或者 geeksforgeeks 更侧重于示例。请注意golang's automatic dereferencing

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-09
        • 2017-07-31
        • 2012-11-25
        • 2013-08-07
        相关资源
        最近更新 更多