简介
Go (Golang) 是谷歌开发的一种现代编译型语言,非常适合构建高负载网络服务。内置的 net/http 包提供了一个强大且灵活的 HTTP 客户端,可以轻松与 REST API、Web 服务器和其他 HTTP 资源进行交互。然而,尽管看似简单,新手经常犯一些典型错误:忘记关闭响应体、不处理超时或忽略错误。
在本文中,我们将详细讲解如何正确使用 Go 中的 HTTP 客户端。您将学习如何发起 GET 和 POST 请求、管理请求头、配置超时以及处理错误。所有代码示例都可在您的项目中直接使用。
1. 基础:GET 请求与读取响应
执行 GET 请求最简单的方法是使用 http.Get() 函数。但对于生产级代码,建议创建自己的 http.Client 实例——这样可以更好地控制客户端的行为。
简单的 GET 请求
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
// 创建客户端(暂时使用默认设置)
client := &http.Client{}
// 执行 GET 请求
resp, err := client.Get("https://api.example.com/data")
if err != nil {
fmt.Fprintf(os.Stderr, "请求错误: %v", err)
os.Exit(1)
}
// 重要:关闭响应体
defer resp.Body.Close()
// 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Fprintf(os.Stderr, "读取响应体错误: %v", err)
os.Exit(1)
}
fmt.Printf("状态: %s", resp.Status)
fmt.Printf("响应体: %s", body)
}
关键点:
defer resp.Body.Close()— 务必关闭响应体,否则会导致资源泄漏(连接无法返回连接池)。- 始终检查
err— 网络不稳定,请求可能失败。 - 检查 HTTP 响应状态码 (
resp.StatusCode),以区分成功 (2xx) 和服务器错误 (4xx, 5xx)。
2. 带请求体和请求头的 POST 请求
要向服务器发送数据(例如 JSON),可以使用 http.Post() 或更灵活的方法 http.NewRequest() 配合 client.Do()。第二种方法更推荐,因为它允许设置请求头和其他参数。
带 JSON 数据的 POST 请求
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
func main() {
client := &http.Client{}
// 准备数据
user := User{Name: "伊万·彼得罗夫", Email: "ivan@example.com"}
jsonData, err := json.Marshal(user)
if err != nil {
fmt.Fprintf(os.Stderr, "JSON 序列化错误: %v", err)
os.Exit(1)
}
// 创建请求
req, err := http.NewRequest("POST", "https://api.example.com/users", bytes.NewBuffer(jsonData))
if err != nil {
fmt.Fprintf(os.Stderr, "创建请求错误: %v", err)
os.Exit(1)
}
// 设置请求头
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_TOKEN_HERE")
// 发送请求
resp, err := client.Do(req)
if err != nil {
fmt.Fprintf(os.Stderr, "请求错误: %v", err)
os.Exit(1)
}
defer resp.Body.Close()
// 检查状态码
if resp.StatusCode != http.StatusCreated {
fmt.Fprintf(os.Stderr, "服务器返回错误: %s", resp.Status)
os.Exit(1)
}
fmt.Println("用户创建成功!")
}
重要