Go HTTP 请求完整指南

1. 导入必要包

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"
    "time"
)
  • net/http: 核心HTTP客户端和服务器功能
  • encoding/json: JSON编解码
  • io/ioutil: 读取响应体
  • bytes: 构建请求体
  • net/url: URL解析和查询参数构建
  • time: 设置超时

2. 创建不同HTTP方法请求

基础请求创建

func createRequest(method, url string, body io.Reader) (*http.Request, error) {
    req, err := http.NewRequest(method, url, body)
    if err != nil {
        return nil, fmt.Errorf("创建请求失败: %v", err)
    }
    return req, nil
}

3. 设置请求参数

设置Headers

req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer token123")
req.Header.Add("X-Custom-Header", "value")

设置查询参数

params := url.Values{}
params.Add("page", "1")
params.Add("limit", "10")
req.URL.RawQuery = params.Encode()

设置请求体

JSON请求体

type RequestData struct {
    Name  string `json:"name"`
    Value int    `json:"value"`
}

data := RequestData{Name: "test", Value: 42}
jsonData, err := json.Marshal(data)
if err != nil {
    return fmt.Errorf("JSON编码失败: %v", err)
}

req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Content-Type", "application/json")

Form表单数据

formData := url.Values{}
formData.Set("username", "admin")
formData.Set("password", "123456")

req, err := http.NewRequest("POST", url, strings.NewReader(formData.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

4. 配置HTTP客户端

基础客户端

client := &http.Client{
    Timeout: 10 * time.Second, // 设置超时
}

高级配置

client := &http.Client{
    Timeout: 30 * time.Second,
    Transport: &http.Transport{
        MaxIdleConns:        100,
        IdleConnTimeout:     90 * time.Second,
        TLSHandshakeTimeout: 10 * time.Second,
    },
}

5. 处理响应

resp, err := client.Do(req)
if err != nil {
    return fmt.Errorf("请求失败: %v", err)
}
defer resp.Body.Close() // 重要:确保关闭响应体

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
    return fmt.Errorf("读取响应体失败: %v", err)
}

// 检查状态码
if resp.StatusCode != http.StatusOK {
    return fmt.Errorf("非预期状态码: %d, 响应: %s", resp.StatusCode, string(body))
}

// 解析JSON响应
var result map[string]interface{}
if err := json.Unmarshal(body, &result); err != nil {
    return fmt.Errorf("解析JSON响应失败: %v", err)
}

fmt.Printf("响应: %+v\n", result)

6. 最佳实践

  1. 重用客户端: 避免为每个请求创建新客户端
  2. 设置超时: 防止请求挂起
  3. 关闭响应体: 使用defer确保关闭
  4. 错误处理: 检查每个可能出错的地方
  5. 连接池: 使用Transport配置优化连接
  6. 重试机制: 对临时错误实现重试逻辑

7. 完整POST请求示例

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

type Post struct {
    UserID int    `json:"userId"`
    Title  string `json:"title"`
    Body   string `json:"body"`
}

func main() {
    // 1. 准备数据
    post := Post{
        UserID: 1,
        Title:  "Go HTTP请求示例",
        Body:   "这是一个完整的HTTP POST请求示例",
    }

    // 2. 编码为JSON
    jsonData, err := json.Marshal(post)
    if err != nil {
        fmt.Printf("JSON编码失败: %v\n", err)
        return
    }

    // 3. 创建请求
    req, err := http.NewRequest(
        "POST", 
        "https://jsonplaceholder.typicode.com/posts", 
        bytes.NewBuffer(jsonData),
    )
    if err != nil {
        fmt.Printf("创建请求失败: %v\n", err)
        return
    }

    // 4. 设置Headers
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Bearer example-token")

    // 5. 配置客户端
    client := &http.Client{
        Timeout: 10 * time.Second,
    }

    // 6. 发送请求
    resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("请求失败: %v\n", err)
        return
    }
    defer resp.Body.Close()

    // 7. 处理响应
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("读取响应失败: %v\n", err)
        return
    }

    // 8. 检查状态码
    if resp.StatusCode != http.StatusCreated {
        fmt.Printf("非预期状态码: %d, 响应: %s\n", resp.StatusCode, string(body))
        return
    }

    // 9. 解析响应
    var createdPost Post
    if err := json.Unmarshal(body, &createdPost); err != nil {
        fmt.Printf("解析响应失败: %v\n", err)
        return
    }

    fmt.Printf("创建成功! ID: %d\n", createdPost.UserID)
    fmt.Printf("完整响应: %+v\n", createdPost)
}

这个示例展示了完整的HTTP POST请求流程,包括数据准备、请求创建、客户端配置、请求发送、响应处理和错误处理。

posted @ 2025-12-30 16:36  shuix1ng  阅读(0)  评论(0)    收藏  举报