在Go中使用struct获取json数据

I am facing a rather simple problem in Go since I am totally new to it. I want to fetch and print data from a REST api. the code I have written:

package main

import (
  _"bytes"
  "encoding/json"
  "fmt"
  "io/ioutil"
  "net/http"
)

type Headers struct {
  Headers HttpHeaders `json:"headers"`
}

type HttpHeaders struct {
  Accept string
  Accept_Encoding string `json:"Accept-Encoding"`
  Accept_Language string `json:"Accept-Language"`
  Connection string
  Cookie string
  Host string
  Referer string
  Upgrade_Insecure_Requests bool `json:"Upgrade-Insecure-Requests"`
  User_Agent string `json:"User-Agent"`
}


func main() {
  url := "http://httpbin.org/headers"
  res, err := http.Get(url)
  if err != nil {
    panic(err)
  }
  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    panic(err)
  }
  var head Headers
  err = json.Unmarshal(body, &head)
  if err != nil {
    panic(err)
  }
  fmt.Printf("%+v
", head)


}

After the adjustments I made, the response looks like:

{Headers:{Accept: Accept_Encoding:gzip Accept_Language: Connection:close Cookie: Host:httpbin.org Referer: Upgrade_Insecure_Requests:false User_Agent:}}

I have still some fields without a value and the value in Upgrade_Insecure_requests does not seem to match the one that is returned via the API.

2nd edit: Removed the spaces in the tags. The response now still looks not good.

{Headers:{Accept: Accept_Encoding:gzip Accept_Language: Connection:close Cookie: Host:httpbin.org Referer: Upgrade_Insecure_Requests:false User_Agent:Go-http-client/1.1}}

The Upgrade_insecure_Requests is still 0 instead of 1 and the other fields are still blank.

Change your last line to

fmt.Printf("%+v
", head)

to see all of your fields. As you can see all of strings are empty. It's because in Headers struct headers field is not exported (first letter must be capital) and no data will be unmarshaled into it. Also some fields name don't match the data in http://httpbin.org/headers.

For example change Accept_Encoding field in struct as follows:

    Accept_Encoding string `json:"Accept-Encoding"`

to read from Accept-Encoding instead of Accept_Encoding.

A couple of issues here, first you must export the "HttpHeaders" field of the "Headers" struct, and second, you must tag the fields with JSON names if their JSON key isn't the same (case insensitive):

type Headers struct {
  // The "Headers" member must have a capital "H" so that the
  // JSON marshaler knows that it can be de/serialized.
  Headers HttpHeaders
}

type HttpHeaders {
  Accept          string
  // Since the JSON key is the same as the field name we don't need a tag.
  Accept_Encoding string `json:"Accept-Encoding"`
  // Here we need a tag since the member name cannot contain a dash.
  // ...
}

Note that the "Headers" field of the "Headers" struct doesn't need a JSON tag because the unmarshaler ignores capitalization when matching JSON document keys to go struct field names. That is, the "Header" field would be populated by the JSON key "header", or "Header", or even "HEADER".