我向服务器发送请求并从一个获得答案。你可以看到我的代码:
// Some code
queryUrl, err := url.Parse(someValidStringUrl)
resp, err := client.Get(queryUrl.String())
让我们检查err
:
if err != nil {
log.Panic("Responce:", resp, "\nError:", err)
}
在此之后,我想得到我的回应。我这样做,但我得到空字节切片:
var bytes []byte
n, err := resp.Body.Read(bytes)
if err != nil {
log.Panic(err)
}
log.Println(n, string(bytes))
输出示例:
2017/07/13 16:32:36 0
Here我发现了另一种方式:
// Some code
queryUrl, err := url.Parse(someValidStringUrl)
resp, err := client.Get(queryUrl.String())
if err != nil {
log.Panic("Responce:", resp, "\nError:", err)
}
defer resp.Body.Close()
if resp.StatusCode == 200 { // OK
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Panic(err)
}
log.Println(string(bodyBytes))
}
输出示例:
<html lang='en'>
<head>
</head>
<body>
<title>Hello world</title>
</body>
</html>
&#13;
请帮帮我。这些例子之间有什么区别?为什么我的方式不起作用?
答案 0 :(得分:1)
来自Golang的Reader documentation
读取读取最多len(p)个字节到p。它返回读取的字节数(0 <= n <= len(p))和遇到的任何错误。即使Read返回n&lt; len(p),它可以在调用期间将所有p用作临时空间。如果某些数据可用但不是len(p)字节,则Read会按常规返回可用内容而不是等待更多内容。
当Read成功读取n&gt;后遇到错误或文件结束条件时0字节,它返回读取的字节数。它可以从同一个调用返回(非零)错误,或者从后续调用中返回错误(和n == 0)。这种一般情况的一个例子是Reader在输入流的末尾返回非零数量的字节可能返回err == EOF或err == nil。下一个Read应返回0,EOF。
//Reader interface from package documentation showing 'p' is the input byte slice.
type Reader interface {
Read(p []byte) (n int, err error)
}
由于您从不初始化切片,len(bytes)
始终为0,因此它只读取0个字节。要像您尝试那样手动执行,您必须将切片初始化为非空,然后多次调用读取,直到它最终返回0和EOF,同时将字节附加到您维护的某个缓冲区。这就是为什么需要ioutil.ReadAll,它保证一切都被正确读取,你不必担心处理它。
另请注意示例中的defer resp.Body.Close()
。重要的是要始终记住在使用它们之后关闭读者和作家。
答案 1 :(得分:-1)
响应正文是一个读者。根据文件:
读取读取最多len(p)个字节到p。它返回字节数 读取(0&lt; = n&lt; = len(p))并遇到任何错误。即使阅读 返回n&lt; len(p),它可以使用所有p作为临时空间 呼叫。如果某些数据可用但不是len(p)字节,则读取 通常会返回可用的内容,而不是等待更多内容。
由于字节片var bytes []byte
的长度在传递给Read时为0,因此它永远不会返回任何字节。
您可以做的是将您的[]字节初始化为与返回的内容相同的大小:
bytes := make([]byte, resp.ContentLength)
或者,只需使用ioutil.ReadAll。