Golang request.Body.Close() 返回一个空文档

问题描述 投票:0回答:1

我在 2 个不同的包中有 2 个方法,其中 func B() 接受一个 url 读取网页并返回 *html.Tokenizer。但问题是,只有当我评论 defer r.Body.Close() 时,它才能正常工作,如果我启用它,则从 func B 返回的此文档为空。

如果这两个函数合并为一个函数,它也可以工作。但我需要它们在 2 个不同的包装中。

我在这里缺少什么有什么建议或想法吗? res.Body 不应该关闭吗?

func  (s ParserService) A(u string) (*domain.Result, error) {
    doc, err := s.B("https://www.google.com/")
    if err != nil {
        fmt.Println(err.Error())
    }
    for tokenType := doc.Next(); tokenType != html.ErrorToken; {
        token := doc.Token()
        fmt.Println(token)
        tokenType = doc.Next()
    }
}

func (c Downloader) B(url string) (*html.Tokenizer, error) {
    r, err := c.httpClient.Get(url)
    if err != nil {
        return nil, err
    }
//    defer r.Body.Close()
    doc := html.NewTokenizer(r.Body)
    return doc, nil
}
go http response defer-keyword
1个回答
1
投票

tl;博士

html.Tokenier
Next
方法直接从阅读器读取。在通过分词器完成处理之前,不要关闭主体。在您的示例中,您应该执行 HTTP 请求并在同一函数中对正文进行标记,然后您可以取消注释延迟关闭。

详情

html.Tokenizer
接受
io.Reader
,分词器将从中读取,直到收到
io.EOF
错误。此“错误”表示没有任何内容可供读取,并且标记器源已完成。

http.Request.Body
io.ReadCloser
,它是
io.Reader
io.Closer
的组合。调用
Close
后发生的情况是特定于实现的,但是对于 http.Request.Body,在调用 close 后无法从读取器读取更多字节。

您的问题最终是由于过早关闭

http.Request.Body
(
io.ReadCloser
) 造成的。

© www.soinside.com 2019 - 2024. All rights reserved.