resp.Body的内容存储在哪里?

时间:2020-05-02 08:17:02

标签: go interface

我今天做了一个简单的网址检索器。

1 resp, _ := http.Get("http://www.yahoo.com")
2 text, _ := ioutil.ReadAll(resp.Body)
3 resp.Body.Close()
4 fmt.Printf("%s", text)

结果已按预期打印。但是,我不明白为什么会这样。

根据我对第2行ioutil.ReadAll(resp.Body)的理解,返回[]个字节,这些字节将被馈送到“文本”变量。

但是:

  • resp是* http.Response结构
  • resp.Body是io.ReadCloser接口
  • io.ReadCloser实现io.Reader和io.Closer接口
  • io.Reader签名为(p [] byte)(n int,错误,错误)

那么,resp.Body的那些内容存储在哪里? (反对我目前的接受,即“身体”的内容“神奇地”来自某处)

1 个答案:

答案 0 :(得分:0)

正如@Eklayvya在评论中提到的,响应主体按需流式传输。但是要添加更多上下文。当您致电http.Get()时。 Get()软件包中的http/client函数初始化一个http.DefaultClient,该Get代表您使用默认的HTTP标头和元数据创建请求。

实际上,对源代码的一窥便发现http.NewRequest()只是用于创建新HTTP请求的更常见的http.Do(req *Request)函数的包装。该请求是通过对func send(ireq *Request, rt RoundTripper, deadline time.Time)的基础调用创建的,该调用接受请求,执行其他格式化,然后将请求发送到相关服务器。

有关更多详细信息,http/client.go文件中有一个RoundTripper,它实际上执行http请求。如果您从函数签名中注意到,它将使用您的请求和一个名为// https://golang.org/src/net/http/client.go (line 117) // RoundTripper is an interface representing the ability to execute a // single HTTP transaction, obtaining the Response for a given Request. // // A RoundTripper must be safe for concurrent use by multiple // goroutines. type RoundTripper interface { ... RoundTrip(*Request) (*Response, error) } 的第二个参数。这是事情变得更有趣的地方。

RoundTrip

Request接受Response并返回包含正文的response.Body。网络在这里传输[]byte的字节,因此您可以从网络接收RoundTripperhttp.DefaultClient接口的实现取决于调用者的要求。在这种情况下,它是ClientConn。但是,您可以覆盖它并执行您想要的操作。

几个网络库确实实现了此接口。一个示例是golang.org/x/net/http2包中的RoundTrip结构。第970行包含一个process_img的实现,并将其主体写入其中。实现非常复杂,因为它可以满足并发,超时和其他网络方面的考虑。如果有兴趣,可以看看。

这里是blob