How to use http Response method Read in go?

huangapple go评论147阅读模式
英文:

How to use http Response method Read in go?

问题

好的,我将为你翻译以下内容:

"我已经有一段时间没有使用Go语言了,似乎忘记了如何阅读文档。

如果我像这样进行一个GET请求...

resp, err := http.Get("https://example.com")

然后我发现响应中有一个Body,它是一个io.ReadCloser类型的对象(https://golang.org/pkg/io/#ReadCloser)。我看到ReadCloserReaderCloser的接口。

当我查看Reader接口时,我发现它有一个Read方法,用于将字节读入p(https://golang.org/pkg/io/#Reader)。

总结一下,http Response有一个Body,它是一个io.ReadCloser接口,它本身包含一个Reader接口,该接口有一个Read方法。

当我尝试这样做时,我期望将响应的字节读入HTML,但是我什么都没有看到...

var html []byte
num, err := resp.Body.Read(html)
fmt.Println("\n\thtml: ", html)
fmt.Printf("\n\tnum: %v, err: %v\n", num, err)

输出:

html:  []
num: 0, err: <nil>

我在这里漏掉了什么?"

英文:

It's been a while since I dealt with go and I seem to have forgotten how to read the docs.

If I do a get request like this...

resp, err := http.Get(&quot;https://example.com&quot;)

I then see that the response has a Body that is of an io.ReadCloser type (https://golang.org/pkg/io/#ReadCloser). I see the ReadCloser is an interface to Reader and Closer.

When I look at the Reader interface I see it has a Read method that reads bytes into p (https://golang.org/pkg/io/#Reader).

To recap, the http Response has a body which is a io.ReadCloser Interface which itself contains a Reader interface which has a Read method.

When I try this I would expect to Read the response bytes into HTML, but I see nothing...

var html []byte
num, err := resp.Body.Read(html)
fmt.Println(&quot;\n\thtml: &quot;, html)
fmt.Printf(&quot;\n\tnum: %v, err: %v\n&quot;, num, err)

Output:

html:  []
num: 0, err: &lt;nil&gt;

What am I missing here?

答案1

得分: 8

简短回答:您正在传递一个切片 html,其中 html 的长度将为 '0',而 Read 函数会读取 len(html) 字节到 html 中。

以下是代码的翻译部分:

package main

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

func main() {
	resp, err := http.Get("http://httpbin.org/ip")
	if err != nil {
		fmt.Println("发生请求错误", err.Error())
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("读取响应错误", err.Error())
		return
	}
	fmt.Println("响应\n", string(body))
}

在这里是 链接,在 Go Playground 中无法进行 HTTP 请求,这是一种安全预防措施,所以您可以在自己的计算机上测试这段代码。

英文:

short answer: You are passing a slice html where its len would be '0' and Read reads up to len(html) bytes into html

Here is snippet from https://golang.org/pkg/io/#Reader
> Read reads up to len(p) bytes into p. It returns the number of bytes
> read (0 <= n <= len(p)) and any error encountered. Even if Read
> returns n < len(p), it may use all of p as scratch space during the
> call. If some data is available but not len(p) bytes, Read
> conventionally returns what is available instead of waiting for more.

Now what you may do use ioutil and update the code as

body, err := ioutil.ReadAll(resp.Body)

Code

package main

import (
	&quot;fmt&quot;
	&quot;io/ioutil&quot;
	&quot;net/http&quot;
)

func main() {
	resp, err := http.Get(&quot;http://httpbin.org/ip&quot;)
	if err != nil {
		fmt.Println(&quot;Error making request&quot;, err.Error())
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(&quot;Error reading response&quot;, err.Error())
		return
	}
	fmt.Println(&quot;Response\n&quot;, string(body))
}

Here is play link, in go playground HTTP requests won't work it is a security precaution so you may test this in your machine

答案2

得分: 1

请尝试使用"io/ioutil"包:

import "io/ioutil"
...
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
fmt.Println(string(body))
英文:

Try to use "io/ioutil" package:

import &quot;io/ioutil&quot;
...
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
fmt.Println(string(body)

答案3

得分: 0

你缺少一个好的助手和朋友ReadAll()

你的代码应该像这样:

import "io/ioutil"

resp, err := http.Get("https://example.com")
// 检查错误

defer resp.Body.Close() // 如果我们想重用连接,我们必须关闭Body

html, err := ioutil.ReadAll(resp.Body)
// 检查错误

fmt.Println(string(html))
英文:

You're missing a good helper and friend ReadAll()

Your code should looks like this:

import &quot;io/ioutil&quot;

resp, err := http.Get(&quot;https://example.com&quot;)
// check err

defer resp.Body.Close() // we have to close Body if we want to reuse the connection

html, err := ioutil.ReadAll(resp.Body)
// check err

fmt.Println(string(html))

huangapple
  • 本文由 发表于 2017年1月16日 10:30:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/41668644.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定