http.Get error handling issue

in the following code, if I put a wrong url then it panic error, in this case I don’t think defer received.Body.Close() ever get executed. Am I right? if I’m right, how can I make sure the underlining TCP get closed even in case of error (like giving wrong url)?

package main

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

func main(){
	received, err := http.Get("http://gobyexample.com")
	if err != nil {
		panic(err)
	}
	defer received.Body.Close()
	fmt.Println("status: ", received.Status)
	scanner := bufio.NewScanner(received.Body)
	for i := 0; scanner.Scan() && i < 5; i++{
		fmt.Println(scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		panic(err)
	}
}

meanwhile, when I use defer recived.Body.Close() in goland it highlight it in yellow showing unhandled error, is there something wrong with defer received.Body.Close()?

How/where can I see the result of received.Body.Close()?

1 Like

received.Body.Close() is not executed because panic comes first. I first this is right in this code.
You can use a func in your defer. For example

defer func() {
		fmt.Println("Running defer...")
		received.Body.Close()
	}()
1 Like

Ok. so How can I make sure the underlining TCP get closed even when there is error in this case? or I don’t need to close this TCP in this scenario since the wrong url won’t get any response nor TCP needs to be set up?

and How/where I can see the result of received.Body.Close()?

1 Like

I think you have to check if received is nil inside your defer because and error in http.Get

defer func() {
  if received != nil {
    fmt.Println("Body closing...")
     received.Body.Close()
}
}()
2 Likes

You are right. The close won’t be executed in case of error. In order to enforce its execution, even in case of error, put the defer close before the test if error.

Actually, when http.Get returns a non nil error, resp may still be not nil. It is also required to ensure all data from the response has been read to be able to reuse the connection.

This is the right way to perform an http get request in Go.

received, err := http.Get("http://gobyexample.com")
if received != nil {
    defer func() {
        _, err = io.Copy(ioutil.Discard, received.Body)
        received.Body.Close()
    }()
}
if err != nil {
    panic(err)
}
2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.