Go的http.DefaultClient阻塞直到身体的最后一个字节?

时间:2015-04-21 16:48:39

标签: http go

例如,如果我有代码

t := time.Now()
http.Get("google.com")
fmt.Println(time.Now().Sub(t))

打印的持续时间是在响应主体的最后一个字节之后还是在收到响应标题的最后一个字节之后?

1 个答案:

答案 0 :(得分:1)

documentation没有明确说明这一点,但是一旦读取了响应标题就会返回。

只要您获得Go的一点经验,您就会发现几乎每次返回时io.Reader(或者在这种情况下resp.Body都是io.ReadCloser)它就是流媒体阅读器还没有所有数据。 就像调用os.Open返回可以用作io.Reader但不会读取整个文件的东西一样。

在Go的许多情况下,如果文档不清楚, 你可以看一下standard package code的启示。 不可否认,在这种特定情况下(与encoding/json一样)代码正在做很多事情,所以乍看之下很难遵循。 大多数标准软件包都更容易理解和学习。

如果做不到这一点,你可以运行你给的代码的一个小扩展(在你自己的机器上,操场上不支持建立TCP连接),使其非常清楚:

(注意我只是随机选择了这些网址,最好是选择一些带有大量有效负载的网址,你知道没有人会介意你去测试)

package main

import (
    "fmt"
    "io"
    "io/ioutil"
    "net/http"
    "time"
)

func measure(url string) (t1, t2 time.Duration, n int64, err error) {
    start := time.Now()
    resp, err := http.Get(url)
    if err != nil {
        return
    }
    defer resp.Body.Close()
    t1 = time.Since(start)
    n, err = io.Copy(ioutil.Discard, resp.Body)
    t2 = time.Since(start)
    return
}

func main() {
    for _, url := range []string{
        "http://google.com/",
        "http://en.wikipedia.org/",
        "http://upload.wikimedia.org/wikipedia/commons/7/76/PIA02863_-_Jupiter_surface_motion_animation.gif",
    } {
        fmt.Printf("fetching %q ", url)
        t1, t2, n, err := measure(url)
        if err != nil {
            fmt.Println("error:", err)
            continue
        }
        fmt.Printf("got %d bytes in %v / %v\n", n, t1, t2)
    }
}

E.g。在一个有点慢的连接上,上面测量的最终URL表示:597.055907ms / 29.269763851s。 (也就是说,初始Get调用快速返回,而读取所有数据需要大约60倍。)