
在go中执行http请求时,必须先检查错误再defer关闭响应体,否则可能因resp为nil导致panic;正确的模式是立即检查err是否非nil,成功后再defer resp.body.close()。
在go中执行http请求时,必须先检查错误再defer关闭响应体,否则可能因resp为nil导致panic;正确的模式是立即检查err是否非nil,成功后再defer resp.body.close()。
进行HTTP客户端调用(如 http.Get)时,Go的约定是:*函数返回值中若包含指针类型(如 `http.Response)和错误(error),则当错误非nil时,该指针保证为nil**。因此,若未先检查错误就直接使用resp.Body`,将触发运行时 panic:“invalid memory address or nil pointer dereference”。
✅ 正确做法:
在获取 resp, err 后立即检查 err,仅当 err == nil 时才安全访问 resp,并在此后安排 defer resp.Body.Close():
resp, err := http.Get("https://www.google.com")
if err != nil {
log.Printf("HTTP request failed: %v", err)
return err // 或适当处理错误(如返回、重试、fallback)
}
defer resp.Body.Close() // 此时 resp 必然非nil,可安全 defer
// 后续读取响应体(如 io.ReadAll、json.Unmarshal 等)
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Printf("Failed to read response body: %v", err)
return err
}⚠️ 常见错误写法(危险!):
resp, err := http.Get("https://example.com")
defer resp.Body.Close() // 错误!resp 可能为 nil → panic
if err != nil {
return err
}此代码在 err != nil 时仍会执行 defer,试图对 nil.Body 调用 Close(),导致程序崩溃。
? 补充说明:
立即学习“go语言免费学习笔记(深入)”;
- defer 语句在定义时即求值其参数(resp.Body),但实际执行延迟到函数返回前。因此,defer resp.Body.Close() 中的 resp 必须在 defer 语句执行时已确定为非nil——这正是为何必须在 defer 前完成错误检查。
- 即使后续读取 resp.Body 出错(如网络中断、解码失败),defer 仍会确保已打开的 Body 被关闭,避免连接泄漏。
- 对于需要复用 http.Client 或自定义配置的场景,该原则同样适用(如 client.Do(req)),核心逻辑不变:先验错,再 defer。
总结:Go 的错误处理强调“显式、即时、就近”。始终遵循「调用 → 检查错误 → 安全使用资源 → defer 清理」这一流程,既是语言惯用法,也是保障程序健壮性的关键实践。


















