簡體   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