引言:为什么 Go 语言中的 HTTP 客户端值得关注
现代 Web 应用程序很少独立运行。几乎每个服务都会通过 HTTP 与外部 API、微服务或第三方资源进行交互。Go 语言(Golang)提供了强大的内置库 net/http,无需第三方依赖即可创建高效、高性能的 HTTP 客户端。
在本文中,我们将详细讲解如何在 Go 中正确使用 HTTP 客户端:从简单的 GET 请求到错误处理和超时管理。你将学会如何避免常见错误并编写可靠的代码。
Go 语言 HTTP 客户端基础
Go 的 net/http 库在设计上注重性能。与许多其他语言每次请求都创建新连接不同,Go 默认使用连接池。这意味着 TCP 连接会被复用,从而显著提升操作速度。
简单的 GET 请求
让我们从最简单的示例开始——使用 http.Get() 函数发送 GET 请求:
package main
import ( "fmt" "io" "net/http" "os")
func main() { // Simple GET request resp, err := http.Get("https://api.github.com") if err != nil { fmt.Printf("Error executing request: %v", err) os.Exit(1) } defer resp.Body.Close()
// Read response body body, err := io.ReadAll(resp.Body) if err != nil { fmt.Printf("Error reading response: %v", err) os.Exit(1) }
fmt.Printf("Status: %s", resp.Status) fmt.Printf("Response body: %s", string(body))}重要提醒:始终关闭响应体(resp.Body.Close())。使用 defer 确保即使在发生错误时也能正常关闭。
带参数和请求头的 GET 请求
对于更复杂的请求,最好使用完整语法,通过创建 http.Request 对象来实现:
package main
import ( "fmt" "io" "net/http" "time")
func main() { // Create a new client client := &http.Client{ Timeout: 10 * time.Second, }
// Create a request req, err := http.NewRequest("GET", "https://api.example.com/users", nil) if err != nil { fmt.Printf("Error creating request: %v", err) return }
// Add headers req.Header.Set("Authorization", "Bearer your-token-here") req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", "Go-http-client/1.0")
// Add query parameters q := req.URL.Query() q.Add("limit", "10") q.Add("offset", "0") req.URL.RawQuery = q.Encode()
// Execute the request resp, err := client.Do(req) if err != nil { fmt.Printf("Error executing request: %v", err) return } defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body) fmt.Printf("Response: %s", string(body))}处理 POST 请求与 JSON
带 JSON 请求体的 POST 请求是使用 REST API 时的标准任务。Go 提供了便捷的数据序列化工具。
通过 POST 发送 JSON
package main
import ( "bytes" "encoding/json" "fmt" "net/http" "time")
type User struct { Name string `json:"name"` Email string `json:"email"` Age int `json:"age"`}
func main() { user := User{ Name: "Ivan Petrov", Email: "ivan@example.com", Age: 30, }
// Serialize the struct to JSON jsonData, err := json.Marshal(user) if err != nil { fmt.Printf("JSON serialization error: %v", err) return }
client := &http.Client{Timeout: 5 * time.Second}