Go语言HTTP客户端:从A到Z正确发送请求

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么在Go中掌握HTTP工作很重要

\n

Go(Golang)是一种为网络工作而设计的语言。其标准库net/http提供了强大且灵活的工具,用于创建服务器和客户端。然而,许多开发者,尤其是从脚本语言转来的,常犯典型错误:忘记关闭响应体、未设置超时或错误处理不当。

\n

在本文中,我们将从A到Z讲解如何在Go中创建HTTP客户端。您将学习如何正确发送GET和POST请求、管理标头、配置超时以及处理错误。所有代码示例均可直接使用。

\n\n

1. 基础:创建客户端和第一个GET请求

\n

在Go中,HTTP客户端是一个http.Client结构体。您可以使用全局客户端http.DefaultClient,或创建具有自定义设置的自有客户端。我们从简单的GET请求开始。

\n
package main\n\nimport (\n    "fmt"\n    "io"\n    "net/http"\n    "os"\n)\n\nfunc main() {\n    // 使用内置客户端\n    resp, err := http.Get("https://api.example.com/data")\n    if err != nil {\n        fmt.Printf("请求错误:%v\\n", err)\n        os.Exit(1)\n    }\n    defer resp.Body.Close() // 重要:始终关闭响应体!\n\n    // 读取响应体\n    body, err := io.ReadAll(resp.Body)\n    if err != nil {\n        fmt.Printf("读取响应错误:%v\\n", err)\n        os.Exit(1)\n    }\n\n    fmt.Printf("状态:%s\\n", resp.Status)\n    fmt.Printf("响应体:%s\\n", string(body))\n}
\n

关键点:

\n
    \n
  • 始终通过defer关闭resp.Body。否则会导致资源泄漏(连接无法返回连接池)。
  • \n
  • 检查响应状态(resp.StatusCode)。200不是唯一成功的状态码(还有201、204等)。
  • \n
  • io.ReadAll将整个响应体读入内存。对于大型响应,请使用io.Copy或流式处理。
  • \n
\n\n

2. 高级客户端:超时、标头和自定义设置

\n

全局客户端默认没有超时——这可能导致程序挂起。始终创建具有设置的自有客户端。

\n

2.1. 创建带超时的客户端

\n
client := &http.Client{\n    Timeout: 10 * time.Second, // 整个请求的总超时\n}\n\nresp, err := client.Get("https://api.example.com/data")
\n

还可以通过Transport在不同级别配置超时:

\n
transport := &http.Transport{\n    DialContext: (&net.Dialer{\n        Timeout:   5 * time.Second, // 连接超时\n        KeepAlive: 30 * time.Second,\n    }).DialContext,\n    TLSHandshakeTimeout:   5 * time.Second,\n    ResponseHeaderTimeout: 5 * time.Second,\n}\n\nclient := &http.Client{\n    Transport: transport,\n    Timeout:   15 * time.Second,\n}
\n\n

2.2. 添加标头和参数

\n

对于复杂请求,使用http.NewRequest:

\n
req, err := http.NewRequest("GET", "https://api.example.com/search", nil)\nif err != nil {\n    log.Fatal(err)\n}\n\n// 添加标头\nreq.Header.Set("Authorization", "Bearer your-token")\nreq.Header.Set("Accept", "application/json")\n\n// 添加查询参数\nq := req.URL.Query()\nq.Add("query", "golang")\nq.Add("page", "1")\nreq.URL.RawQuery = q.Encode()\n\nresp, err := client.Do(req)
\n\n

3. 使用POST和其他方法(JSON、表单)

\n

POST请求需要传递请求体。我们来看两种流行格式:JSON和URL编码表单。

\n

3.1. 带JSON的POST

\n
type RequestData struct {\n    Name  string `json:"name"`\n    Email string `json:"email"`\n}\n\ndata := RequestData{\n    Name:  "伊万",\n    Email: "ivan@example.com",\n}\n\njsonData, err := json.Marshal(da                

博客

书籍推荐