Golang中如何处理http.Get的错误问题

Golang中如何处理http.Get的错误问题 在以下代码中,如果我输入错误的URL,程序就会发生panic错误。这种情况下,我认为defer received.Body.Close()不会被执行。我的理解正确吗?如果正确,如何确保即使在发生错误的情况下(比如提供错误URL)底层的TCP连接也能被关闭?

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)
	}
}

另外,当我在goland中使用defer recived.Body.Close()时,它会用黄色高亮显示,提示unhandled errordefer received.Body.Close()有什么问题吗?

如何/在哪里可以查看received.Body.Close()的结果?


更多关于Golang中如何处理http.Get的错误问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

我认为你需要在defer中检查received是否为nil,因为http.Get可能会返回错误

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

更多关于Golang中如何处理http.Get的错误问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


received.Body.Close() 不会被执行,因为 panic 会先发生。我认为这段代码是正确的。 你可以使用一个函数作为 defer 的参数。例如

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

好的。那么在这种情况下,即使出现错误,我该如何确保底层的 TCP 连接被关闭?或者在这种情况下我不需要关闭这个 TCP 连接,因为错误的网址不会得到任何响应,也不需要建立 TCP 连接?

以及我如何/在哪里能看到 received.Body.Close() 的结果?

received.Body.Close()

你说得对。如果出现错误,close将不会执行。为了确保即使在出错情况下也能执行,应该在错误检查之前使用defer close。

实际上,当http.Get返回非nil错误时,resp可能仍然不是nil。还需要确保读取响应中的所有数据,以便能够重用连接。

这是在Go中执行HTTP GET请求的正确方式。

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)
}

你的理解是正确的。当 http.Get() 返回错误时,received 会是 nil,此时调用 defer received.Body.Close() 会导致 panic,因为你在尝试访问 nil 对象的 Body 字段。

以下是修正后的代码:

package main

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

func main() {
	received, err := http.Get("http://gobyexample.com")
	if err != nil {
		fmt.Printf("HTTP请求失败: %v\n", err)
		return
	}
	defer func() {
		if err := received.Body.Close(); err != nil {
			fmt.Printf("关闭响应体时出错: %v\n", err)
		}
	}()
	
	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 {
		fmt.Printf("读取响应体时出错: %v\n", err)
	}
}

关于 defer received.Body.Close() 的黄色高亮警告,这是因为 Close() 方法返回一个 error,而你没有处理这个可能的错误。在 Go 中,忽略错误返回值通常被认为是不好的实践。

要查看 received.Body.Close() 的结果,你可以这样处理:

defer func() {
    if closeErr := received.Body.Close(); closeErr != nil {
        fmt.Printf("关闭响应体时出错: %v\n", closeErr)
        // 或者记录到日志系统
    }
}()

更完整的错误处理版本:

package main

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

func main() {
	received, err := http.Get("http://gobyexample.com")
	if err != nil {
		log.Printf("HTTP请求失败: %v", err)
		return
	}
	
	defer func() {
		if err := received.Body.Close(); err != nil {
			log.Printf("关闭响应体时出错: %v", err)
		}
	}()
	
	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 {
		log.Printf("读取响应体时出错: %v", err)
	}
}

关键改进点:

  1. 在检查错误后再使用 defer,确保 received 不是 nil
  2. 使用匿名函数处理 Close() 的错误返回值
  3. 使用 log 包或适当的错误处理机制而不是直接 panic
  4. 确保即使发生错误,TCP 连接也能被正确关闭
回到顶部