从 http 响应正文读取 golang

Posted

技术标签:

【中文标题】从 http 响应正文读取 golang【英文标题】:Reading on golang from http responce body 【发布时间】:2017-12-18 08:14:58 【问题描述】:

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

// 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>

请帮帮我。这些例子之间有什么区别?为什么我的方法行不通?

【问题讨论】:

【参考方案1】:

来自 Golang 的Reader documentation

Read 最多将 len(p) 个字节读入 p。它返回读取的字节数 (0

当 Read 在成功读取 n > 0 个字节后遇到错误或文件结束条件时,它返回读取的字节数。它可能会从同一次调用中返回(非零)错误,或者从后续调用中返回错误(并且 n == 0)。这种一般情况的一个例子是,在输入流末尾返回非零字节数的 Reader 可能会返回 err == EOF 或 err == nil。下一次读取应该返回 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 个字节。要像您尝试那样手动执行此操作,您必须将切片初始化为非空,然后多次调用 read 直到它最终返回 0 和 EOF,同时将字节附加到您维护的某个缓冲区。这就是为什么需要ioutil.ReadAll 的原因,它保证所有内容都被正确读取,您不必担心处理它。

还要注意示例中的defer resp.Body.Close()。请务必记住在使用 Readers 和 Writers 后关闭它们。

【讨论】:

【参考方案2】:

响应正文是 Reader。根据文档:

Read 最多将 len(p) 个字节读入 p。它返回字节数 读取 (0

由于当您将字节切片 var bytes []byte 传递给 Read 时,它的长度为 0,因此它永远不会返回任何字节。

您可以做的是将您的 []byte 初始化为与返回的内容相同的大小:

bytes := make([]byte, resp.ContentLength)

或者,只需使用 ioutil.ReadAll。

【讨论】:

不保证Content-Length 是正确的

以上是关于从 http 响应正文读取 golang的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Golang 的 net/http 包读取流响应正文?

从 Elm 中的 HTTP 响应中读取自定义标头

当服务器仅从请求中读取标头时,Http客户端不会收到响应

在 Apache HttpClient 4.x 中多次读取响应正文

如何从 Python 请求调用中提取 HTTP 响应正文?

从 Angular 中的 HttpInterceptor 访问 HTTP 错误响应正文