Go:XML API返回的字符串编码异常

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

Go: XML API returns oddly encoded string

问题

我正在尝试解析来自API的XML响应,当调用fmt.Println并传递响应主体时,我得到一个奇怪的字符串:

&{0xc8200e6140 {0 0} false <nil> 0xc2030 0xc1fd0}

我已确认我可以使用curl访问API并获得预期的XML响应。(使用Postman Chrome扩展发送GET请求也会得到相同的响应。)这是一个编码问题吗?

以下是相关的代码:

type Album struct {
    Title     string `xml:"album>name"`
    Artist    string `xml:"album>artist>name"`
    PlayCount uint64 `xml:"album>playcount"`
}

const lastFMAPIKey string = "<My api key>"
const APIURL string = "http://ws.audioscrobbler.com/2.0/"

func perror(err error) {
    if err != nil {
        panic(err)
    }
}

func getListeningInfo(url string) []byte {
    resp, err := http.Get(url)
    perror(err)
    defer resp.Body.Close()
    // 这是打印上述字符串的那一行
    fmt.Println(resp.Body)
    body, err2 := ioutil.ReadAll(resp.Body)
    perror(err2)
    return body
}

func main() {
    url := APIURL + "?method=user.getTopAlbums&user=iamnicholascox&period=1month&limit=1&api_key=" + lastFMAPIKey
    album := Album{}
    err := xml.Unmarshal(getListeningInfo(url), &album)
    perror(err)
    fmt.Printf(album.Artist)
}

作为参考,打印resp而不仅仅是resp.Body会得到以下结果:

{200 OK 200 HTTP/1.1 1 1 map[Ntcoent-Length:[871]
Connection:[keep-alive] Access-Control-Max-Age:[86400]
Cache-Control:[private] Date:[Thu, 03 Dec 2015 05:16:34 GMT]
Content-Type:[text/xml; charset=UTF-8]
Access-Control-Request-Headers:[Origin, X-Atmosphere-tracking-id, X-Atmosphere-Framework, X-Cache-Date,
Content-Type, X-Atmosphere-Transport, *]
Access-Control-Allow-Methods:[POST, GET, OPTIONS]
Access-Control-Allow-Origin:[*]
Server:[openresty/1.7.7.2]]
0xc8200f6040 -1 [] false map[] 0xc8200b8000 <nil>}

请注意,我只翻译了你提供的代码和相关的输出,不包括其他内容。

英文:

I'm trying to parse the XML response from an API, and when call fmt.Println and pass the response body, I get a weird string:

&amp;{0xc8200e6140 {0 0} false &lt;nil&gt; 0xc2030 0xc1fd0}

I've confirmed that I can curl the API and get XML as expected. (I also get the same response sending a GET request with the Postman Chrome extension.) Is this an encoding issue?

Here's the relevant code:

type Album struct {
	Title     string `xml:&quot;album&gt;name&quot;`
	Artist    string `xml:&quot;album&gt;artist&gt;name&quot;`
	PlayCount uint64 `xml:&quot;album&gt;playcount&quot;`
}

const lastFMAPIKey string = &quot;&lt;My api key&gt;&quot;
const APIURL string = &quot;http://ws.audioscrobbler.com/2.0/&quot;

func perror(err error) {
	if err != nil {
		panic(err)
	}
}

func getListeningInfo(url string) []byte {
	resp, err := http.Get(url)
	perror(err)
	defer resp.Body.Close()
    // this is the line that prints the string above
	fmt.Println(resp.Body)
	body, err2 := ioutil.ReadAll(resp.Body)
	perror(err2)
	return body
}

func main() {
	url := APIURL + &quot;?method=user.getTopAlbums&amp;user=iamnicholascox&amp;period=1month&amp;limit=1&amp;api_key=&quot; + lastFMAPIKey
	album := Album{}
	err := xml.Unmarshal(getListeningInfo(url), &amp;album)
	perror(err)
	fmt.Printf(album.Artist)
}

For reference, printing out resp instead of just resp.Body gives this:

{200 OK 200 HTTP/1.1 1 1 map[Ntcoent-Length:[871]
Connection:[keep-alive] Access-Control-Max-Age:[86400]
Cache-Control:[private] Date:[Thu, 03 Dec 2015 05:16:34 GMT]
Content-Type:[text/xml; charset=UTF-8]
Access-Control-Request-Headers:[Origin, X-Atmosphere-tracking-id, X-Atmosphere-Framework, X-Cache-Date,
Content-Type, X-Atmosphere-Transport, *]
Access-Control-Allow-Methods:[POST, GET, OPTIONS]
Access-Control-Allow-Origin:[*]
Server:[openresty/1.7.7.2]]
0xc8200f6040 -1 [] false map[] 0xc8200b8000 &lt;nil&gt;}

答案1

得分: 2

http.Response的Body是一个io.ReaderCloser。你看到的奇怪输出是作为响应体使用的结构体字段的值。

如果你想要打印出实际的内容,你必须先从Body中读取它。

尝试使用ioutil.ReadAll来实现:

b, err := ioutil.ReadAll(resp.Body) // 这里的b是一个[]byte
if err != nil { 
   fmt.Println("发生错误:", err)
} else {
    fmt.Println(string(b)) // 将[]byte转换为字符串以便打印到屏幕上
}
英文:

The http.Response's Body is an io.ReaderCloser. The odd output you are seeing is the values of the fields of struct used as the response body.

if you want the actual content to print out, you must read it from the Body first.

Try ioutil.ReadAll by doing:

b, err := ioutil.ReadAll(resp.Body) // b is a []byte here
if err != nil { 
   fmt.Println(&quot;Got error:&quot;,err)
} else {
    fmt.Println(string(b)) // convert []byte to string for printing to the screen.
}

huangapple
  • 本文由 发表于 2015年12月3日 13:30:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/34058531.html
匿名

发表评论

匿名网友

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

确定