在Go中嵌套[] struct循环?

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, "
")
            fmt.Print("value: ", value, "
")
      }
}

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.

This code based off an example here should do it for you; 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, "
")
            fmt.Print("value: ", f.Interface(), "
")
       }

}

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.

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:"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)
", v)
        case string:
            fmt.Printf("%v (str)
", v)
        case bool:
            fmt.Printf("%v (bool)
", v)
        default:
            fmt.Printf("%v (%T)
", v, v)
        }
    }
}

playground

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

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, "
")
      }
}