首先检查请求发送阶段的错误,如连接超时、DNS解析失败等;再判断HTTP状态码是否为200或预期范围;设置客户端超时避免阻塞;最后读取响应体时处理可能的传输错误,并始终关闭Body。
在Go语言中处理网络请求返回的错误,关键在于正确使用
包并检查多个可能出错的环节。很多开发者只关注HTTP
状态码
,却忽略了更底层的连接、超时或DNS解析等错误,这会导致程序稳定性下降。
检查请求发送阶段的错误
调用
或
等方法时,第一个要判断的是是否成功发出请求。这类错误通常与网络连接有关,比如主机不可达、超时、TLS握手失败等。
示例:
注意:只要
,就说明请求未成功完成,此时
可能是nil或部分响应,不能直接使用。
立即学习
“
go语言免费学习笔记(深入)
”;
检查HTTP状态码
即使请求发送成功(无error),服务器仍可能返回非200的状态码,如404、500、401等。这些不属于Go的“错误”,但对业务来说是异常情况。
建议根据实际需求判断状态码:
go语言参考手册 中文CHM版
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译
下载
也可以接受某些范围的状态码,比如允许2xx和3xx:
设置超时避免阻塞
默认的
没有超时限制,可能导致请求长时间挂起。应自定义Client并设置合理的超时时间。
更精细的控制可以使用
设置连接、读写等阶段的超时:
读取响应体时也要处理错误
即使请求成功且状态码正常,读取
时仍可能发生错误,比如网络中断、数据截断等。
记得始终调用
释放资源,推荐使用
。
基本上就这些。关键是分清楚不同阶段的错误来源:连接层错误由
返回,应用层错误看状态码,传输过程中读取失败单独处理,再加上合理的超时配置,就能写出健壮的HTTP客户端代码。
net/httphttp.Do()http.Get()
resp, err := http.Get("https://example.com")
if err != nil {
log.Printf("请求失败: %v", err)
// 常见错误类型:
// - net.OpError: 连接超时、DNS解析失败
// - *url.Error: URL格式问题或底层连接错误
// - tls.CertificateError: 证书验证失败
return
}
defer resp.Body.Close()
err != nilresp
if resp.StatusCode != http.StatusOK {
log.Printf("HTTP错误状态: %d", resp.StatusCode)
// 可选择将非200视为错误并处理
return fmt.Errorf("unexpected status: %d", resp.StatusCode)
}
if resp.StatusCode >= 400 {
return fmt.Errorf("bad response: %d", resp.StatusCode)
}
http.Client
client := &http.Client{
Timeout: 10 * time.Second, // 整个请求的最大耗时
}
resp, err := client.Get("https://www.php.cn/link/c071c86446066d4de2ba1551614a08c8")
if err != nil {
log.Printf("请求超时或失败: %v", err)
return
}
Transport
client := &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: 5 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
TLSHandshakeTimeout: 5 * time.Second,
ResponseHeaderTimeout: 5 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
Timeout: 15 * time.Second,
}
resp.Body
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Printf("读取响应体失败: %v", err)
return
}
resp.Body.Close()deferhttp.Do