阅读http.Response Body流

jzm*_*jzm 2 go

我正在发送http请求并以text/xml格式获取响应.我不需要解析XML,只是尝试将其作为字符串返回进行测试.但它似乎很慢.

XML响应是278kb,但它可能需要大约1.7,但有时只需要达到4.5秒才能读取响应体.我可以一遍又一遍地重新运行它,它可以变化很大.我不确定是什么导致它,因为我是Go的新手.

我觉得ioutil.ReadAll()函数让我感到失望.但我也尝试过bufio.NewReader和reader.ReadBytes.一切似乎都很慢.

这就是我的功能:

client := &http.Client{}
req, err := http.NewRequest("POST", url, strings.NewReader(requestBody))
if err != nil {
    fmt.Println("New Request Error", err)
}

// Set Headers
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Content-Encoding", "gzip")
req.Header.Set("Accept-Encoding", "gzip, deflate")

defer req.Body.Close()

// Get Response
startRes := time.Now()
response, err := client.Do(req)
if response != nil {
    defer response.Body.Close()
}
if err != nil {
    fmt.Println("POST Error", err)
}
endRes := time.Now()
fmt.Println("Response took", endRes.Sub(startRes))

// Read Response Body
startRead := time.Now()
body, readErr := ioutil.ReadAll(response.Body)
if readErr != nil {
    fmt.Println("body error:", readErr)
    return nil, readErr
}

endRead := time.Now()
fmt.Println("Read response took:", endRead.Sub(startRead))
Run Code Online (Sandbox Code Playgroud)

这些println的输出如下所示:

> go run main.go
 Response took 5.230523s
 Read response took: 1.7551755s
Run Code Online (Sandbox Code Playgroud)

有没有办法让这个代码更有效?我假设一个278kb文件的1.7s读取时间是由于网络滞后,对吧?

Kev*_*uth 6

我建议byte.Buffer你自己分配并阅读身体.所述代码ioutil.ReadAll创建一个byte.Buffer在的初始容量Byte.MinRead(512个字节).

在278KB时,Buffer需要扩展,重新分配和重新分配返回的字节数组10次,这是大部分处理时间(对于你可以控制的事情).

未经测试的代码可在下面尝试:

buf := bytes.NewBuffer(make([]byte, 0, response.ContentLength))
_, readErr = buf.ReadFrom(response.Body)
body := buf.Bytes()
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,`response.ContentLength` 可以返回 -1,这会在创建缓冲区时导致运行时错误 `makeslice: cap out of range`。 (2认同)