在Go语言中,可以使用嵌套的`[]struct`来进行循环。

huangapple go评论82阅读模式
英文:

looping with nested []struct in Go?

问题

我正在使用的结构,我不确定如何正确地循环遍历它。我想访问字段名,但它只是在每次循环中递增计数。

这是我的结构:

type ImgurJson struct {
    Status int16 `json:"status"`
    Success bool `json:"success"`
    Data []struct {
        Width int16 `json:"width"`
        Points int32 `json:"points"`
        CommentCount int32 `json:"comment_count"`
        TopicId int32 `json:"topic_id"`
        AccountId int32 `json:"account_id"`
        Ups int32 `json:"ups"`
        Downs int32 `json:"downs"`
        Bandwidth int64 `json:"bandwidth"`
        Datetime int64 `json:"datetime"`
        Score int64 `json:"score"`
        Account_Url string `json:"account_url"`
        Topic string `json:"topic"`
        Link string `json:"link"`
        Id string `json:"id"`
        Description string `json:"description"`
        CommentPreview string `json:"comment_preview"`
        Vote string `json:"vote"`
        Title string `json:"title"`
        Section string `json:"section"`
        Favorite bool `json:"favorite"`
        Is_Album bool `json:"is_album"`
        Nsfw bool `json:"nsfw"`
    } `json:"data"`
}

这是我的函数:

func parseJson(file string) {
    jsonFile, err := ioutil.ReadFile(file)
    if err != nil {
        // 错误处理
    }
    jsonParser := ImgurJson{}
    err = json.Unmarshal(jsonFile, &jsonParser)
    for _, data := range jsonParser.Data {
        for field, value := range data {
            fmt.Println("field:", field)
            fmt.Println("value:", value)
        }
    }
}

如何在Go中循环遍历嵌套的[]struct并返回字段?我看到了一些关于反射的帖子,但我不确定它是否对我有帮助。我可以返回每个字段的值,但我不知道如何将字段名映射到键值。

编辑:

将“keys”重命名为“field”,抱歉!我没有意识到它们被称为字段。

我想打印出:

field: Width
value: 1234

我想学习如何做到这一点,以便稍后可以按名称调用特定字段,以便将其映射到SQL列名。

英文:

I have a structure I'm working with, and I'm not sure how to loop through it properly. I would like to access the field names, but all it is doing is just incrementally counting at each loop.

Here is my structure:

type ImgurJson struct {
      Status int16 `json:"status"`
      Success bool `json:"success"`
      Data []struct {
            Width int16 `json:"width"`
            Points int32 `json:"points"`
            CommentCount int32 `json:"comment_count"`
            TopicId int32 `json:"topic_id"`
            AccountId int32 `json:"account_id"`
            Ups int32 `json:"ups"`
            Downs int32 `json:"downs"`
            Bandwidth int64 `json:"bandwidth"`
            Datetime int64 `json:"datetime"`
            Score int64 `json:"score"`
            Account_Url string `json:"account_url"`
            Topic string `json:"topic"`
            Link string `json:"link"`
            Id string `json:"id"`
            Description string`json:"description"`
            CommentPreview string `json:"comment_preview"`
            Vote string `json:"vote"`
            Title string `json:"title"`
            Section string `json:"section"`
            Favorite bool `json:"favorite"`
            Is_Album bool `json:"is_album"`
            Nsfw bool `json:"nsfw"`
             } `json:"data"`
}

Here is my function:

func parseJson(file string) {
      jsonFile, err := ioutil.ReadFile(file)
      if err != nil {
            ...
            }
      jsonParser := ImgurJson{}
      err = json.Unmarshal(jsonFile, &jsonParser)
      for field, value := range jsonParser.Data {
            fmt.Print("key: ", field, "\n")
            fmt.Print("value: ", value, "\n")
      }
}

How do I loop through a nested, []struct in Go and return the fields? I've seen several posts about reflection, but I don't understand if that would assist me or not. I can return the values of each field, but I don't understand how to map the field name to the key value.

Edit:

Renamed "keys" to "field", sorry! Didn't realise they were called fields.

I would like to be able to print:

field: Width
value: 1234

I would like to learn how to do this so I can later call a specific field by name so I can map it to a SQL column name.

答案1

得分: 6

这段代码基于这里的一个示例,应该可以满足你的需求;http://blog.golang.org/laws-of-reflection

import "reflect"

for _, value := range jsonParser.Data {
    s := reflect.ValueOf(&value).Elem()
    typeOfT := s.Type()
    for i := 0; i < s.NumField(); i++ {
        f := s.Field(i)
        fmt.Print("key: ", typeOfT.Field(i).Name, "\n")
        fmt.Print("value: ", f.Interface(), "\n")
    }
}

请注意,在你的原始代码中,循环正在遍历名为Data的切片中的项。每个项都是该匿名结构类型的对象。在那一点上,你并没有处理字段,从那里,你可以利用reflect包来打印结构体中字段的名称和值。你不能直接对结构体进行range操作,因为该操作未定义。

英文:

This code based off an example here should do it for you; http://blog.golang.org/laws-of-reflection

import &quot;reflect&quot;


for _, value := range jsonParser.Data {
            s := reflect.ValueOf(&amp;value).Elem()
            typeOfT := s.Type()
            for i := 0; i &lt; s.NumField(); i++ {
            f := s.Field(i)
            fmt.Print(&quot;key: &quot;, typeOfT.Field(i).Name, &quot;\n&quot;)
            fmt.Print(&quot;value: &quot;, f.Interface(), &quot;\n&quot;)
       }
            
}

Note that in your original code the loop is iterating items in the slice called Data. Each of those things an object of that anonymous struct type. You're not dealing with the fields at that point, from there, you can leverage the reflect package to print the names and values of fields in the struct. You can't just range over a struct natively, the operation isn't defined.

答案2

得分: 1

这是我们在评论中讨论的另一种方法:

请记住,虽然这种方法比反射更快,但直接使用结构字段并将其作为指针(Data []*struct{....})更好和更高效。

type ImgurJson struct {
    Status  int16                    `json:"status"`
    Success bool                     `json:"success"`
    Data    []map[string]interface{} `json:"data"`
}
//.....
for i, d := range ij.Data {
    fmt.Println(i, ":")
    for k, v := range d {
        fmt.Printf("\t%s: ", k)
        switch v := v.(type) {
        case float64:
            fmt.Printf("%v (number)\n", v)
        case string:
            fmt.Printf("%v (str)\n", v)
        case bool:
            fmt.Printf("%v (bool)\n", v)
        default:
            fmt.Printf("%v (%T)\n", v, v)
        }
    }
}

playground

英文:

This is an alternative approach that we discussed in the comments:

Keep in mind that while this is faster than reflection, it's still better and more efficient to use the struct fields directly and make it a pointer (Data []*struct{....}).

type ImgurJson struct {
	Status  int16                    `json:&quot;status&quot;`
	Success bool                     `json:&quot;success&quot;`
	Data    []map[string]interface{} `json:&quot;data&quot;`
}
//.....
for i, d := range ij.Data {
	fmt.Println(i, &quot;:&quot;)
	for k, v := range d {
		fmt.Printf(&quot;\t%s: &quot;, k)
		switch v := v.(type) {
		case float64:
			fmt.Printf(&quot;%v (number)\n&quot;, v)
		case string:
			fmt.Printf(&quot;%v (str)\n&quot;, v)
		case bool:
			fmt.Printf(&quot;%v (bool)\n&quot;, v)
		default:
			fmt.Printf(&quot;%v (%T)\n&quot;, v, v)
		}
	}
}

<kbd>playground</kbd>

答案3

得分: 0

你也可以使用普通的 Golang for 循环来迭代嵌套结构。

type ImgurJson struct {
    Status        int16 `json:"status"`
    Success       bool  `json:"success"`
    Data          []struct {
        Width          int16  `json:"width"`
        Points         int32  `json:"points"`
        CommentCount   int32  `json:"comment_count"`
        TopicId        int32  `json:"topic_id"`
        AccountId      int32  `json:"account_id"`
        Ups            int32  `json:"ups"`
        Downs          int32  `json:"downs"`
        Bandwidth      int64  `json:"bandwidth"`
        Datetime       int64  `json:"datetime"`
        Score          int64  `json:"score"`
        Account_Url    string `json:"account_url"`
        Topic          string `json:"topic"`
        Link           string `json:"link"`
        Id             string `json:"id"`
        Description    string `json:"description"`
        CommentPreview string `json:"comment_preview"`
        Vote           string `json:"vote"`
        Title          string `json:"title"`
        Section        string `json:"section"`
        Favorite       bool   `json:"favorite"`
        Is_Album       bool   `json:"is_album"`
        Nsfw           bool   `json:"nsfw"`
    } `json:"data"`
}

func parseJson(file string) {
    jsonFile, err := ioutil.ReadFile(file)
    if err != nil {
        // 错误处理
    }
    jsonParser := ImgurJson{}
    err = json.Unmarshal(jsonFile, &jsonParser)
    for i := 0; i < len(jsonParser.Data); i++ {
        fmt.Print("key: ", jsonParser.Data[i].TopicId, "\n")
    }
}

以上是给定的代码段的翻译。

英文:

You can also iterate using normal golang for loop on nested struct.

type ImgurJson struct {
      Status int16 `json:&quot;status&quot;`
      Success bool `json:&quot;success&quot;`
      Data []struct {
            Width int16 `json:&quot;width&quot;`
            Points int32 `json:&quot;points&quot;`
            CommentCount int32 `json:&quot;comment_count&quot;`
            TopicId int32 `json:&quot;topic_id&quot;`
            AccountId int32 `json:&quot;account_id&quot;`
            Ups int32 `json:&quot;ups&quot;`
            Downs int32 `json:&quot;downs&quot;`
            Bandwidth int64 `json:&quot;bandwidth&quot;`
            Datetime int64 `json:&quot;datetime&quot;`
            Score int64 `json:&quot;score&quot;`
            Account_Url string `json:&quot;account_url&quot;`
            Topic string `json:&quot;topic&quot;`
            Link string `json:&quot;link&quot;`
            Id string `json:&quot;id&quot;`
            Description string`json:&quot;description&quot;`
            CommentPreview string `json:&quot;comment_preview&quot;`
            Vote string `json:&quot;vote&quot;`
            Title string `json:&quot;title&quot;`
            Section string `json:&quot;section&quot;`
            Favorite bool `json:&quot;favorite&quot;`
            Is_Album bool `json:&quot;is_album&quot;`
            Nsfw bool `json:&quot;nsfw&quot;`
             } `json:&quot;data&quot;`
}

func parseJson(file string) {
      jsonFile, err := ioutil.ReadFile(file)
      if err != nil {
            ...
            }
      jsonParser := ImgurJson{}
      err = json.Unmarshal(jsonFile, &amp;jsonParser)
      for i :=0; i&lt;len(jsonParser.Data); i++ {
            fmt.Print(&quot;key: &quot;, jsonParser.Data[i].TopicId, &quot;\n&quot;)
      }
}

huangapple
  • 本文由 发表于 2015年9月16日 05:48:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/32596255.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定