3

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("https://example.com")

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("\n\thtml: ", html)
fmt.Printf("\n\tnum: %v, err: %v\n", num, err)

Output:

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

What am I missing here?

2
  • You need to allocate space to read into. You're only providing a nil slice, so Read can't read anything. Commented Jan 16, 2017 at 3:05
  • 1
    Read reads up to len(html) bytes into html , here it is zero Commented Jan 16, 2017 at 3:15

3 Answers 3

8

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 io and update the code as

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

Code

package main

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

func main() {
    resp, err := http.Get("http://httpbin.org/ip")
    if err != nil {
        fmt.Println("Error making request", err.Error())
        return
    }
    defer resp.Body.Close()
    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error reading response", err.Error())
        return
    }
    fmt.Println("Response\n", 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

Sign up to request clarification or add additional context in comments.

Comments

1

Try to use "io/ioutil" package:

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

Comments

0

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

Your code should looks like this:

package main

import (
    "fmt"
    "io" // with go v1.15 and below, use "io/ioutil" instead
    "net/http"
)

func main() {
    resp, err := http.Get("https://example.com")
    // check err

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

    html, err := io.ReadAll(resp.Body) // with go v1.15 and below, use `ioutil.ReadAll`
    // check err

    fmt.Println(string(html))
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.