从http response body身上阅读golang

时间:2017-07-13 13:42:36

标签: http go

我向服务器发送请求并从一个获得答案。你可以看到我的代码:

// 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;
&#13;
&#13;

请帮帮我。这些例子之间有什么区别?为什么我的方式不起作用?

2 个答案:

答案 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。