作为 HTTP 客户端 使用 Go 的 net/http 模块时,重点在于如何发送各种 HTTP 请求、处理响应以及灵活使用客户端配置。下面分为常见场景和进阶功能讲解。


1. 基础 HTTP 客户端操作

GET 请求

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    // 简单 GET 请求
    resp, err := http.Get("https://jsonplaceholder.typicode.com/posts/1")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    // 读取响应体
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println("Status Code:", resp.StatusCode) // 打印状态码
    fmt.Println("Body:", string(body))          // 打印响应体
}

POST 请求

发送 JSON 数据:

package main

import (
    "bytes"
    "fmt"
    "net/http"
)

func main() {
    data := []byte(`{"title":"foo","body":"bar","userId":1}`)
    resp, err := http.Post("https://jsonplaceholder.typicode.com/posts", "application/json", bytes.NewBuffer(data))
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    fmt.Println("Status Code:", resp.StatusCode)
}

2. 使用 http.Client 发送自定义请求

http.Client 提供更多控制,适合复杂场景。

自定义请求

通过 http.NewRequest 创建请求,可以添加自定义头部、方法等:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "strings"
)

func main() {
    client := &http.Client{}

    // 创建请求
    req, err := http.NewRequest("POST", "https://jsonplaceholder.typicode.com/posts", strings.NewReader(`{"name":"test"}`))
    if err != nil {
        panic(err)
    }
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Bearer your_token")

    // 发送请求
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    // 读取响应
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println("Response:", string(body))
}

3. 进阶功能

设置超时

避免请求无限制地挂起,使用 http.Client 设置超时:

package main

import (
    "fmt"
    "net/http"
    "time"
)

func main() {
    client := &http.Client{
        Timeout: 5 * time.Second,
    }

    resp, err := client.Get("https://jsonplaceholder.typicode.com/posts/1")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    fmt.Println("Status Code:", resp.StatusCode)
}

处理 Cookie

通过 http.Cookie 发送或接收 Cookie:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    client := &http.Client{}

    req, _ := http.NewRequest("GET", "https://example.com", nil)

    // 设置 Cookie
    req.AddCookie(&http.Cookie{Name: "session_id", Value: "123456"})

    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    // 打印响应 Cookie
    for _, cookie := range resp.Cookies() {
        fmt.Println("Cookie:", cookie)
    }
}

处理重定向

http.Client 默认跟随重定向,但可以自定义行为:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    client := &http.Client{
        CheckRedirect: func(req *http.Request, via []*http.Request) error {
            fmt.Println("Redirected to:", req.URL)
            return nil // 返回错误可阻止重定向
        },
    }

    resp, err := client.Get("http://example.com")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    fmt.Println("Final URL:", resp.Request.URL)
}

4. 文件上传和下载

文件上传

使用 multipart.Writer 构造文件上传请求:

package main

import (
    "bytes"
    "fmt"
    "mime/multipart"
    "net/http"
    "os"
)

func main() {
    file, err := os.Open("example.txt")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)

    part, err := writer.CreateFormFile("file", "example.txt")
    if err != nil {
        panic(err)
    }
    _, err = part.Write([]byte("file content"))
    if err != nil {
        panic(err)
    }
    writer.Close()

    req, _ := http.NewRequest("POST", "https://example.com/upload", body)
    req.Header.Set("Content-Type", writer.FormDataContentType())

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    fmt.Println("Status Code:", resp.StatusCode)
}

文件下载

将响应流直接保存到文件中:

package main

import (
    "io"
    "net/http"
    "os"
)

func main() {
    resp, err := http.Get("https://example.com/file.zip")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    out, err := os.Create("file.zip")
    if err != nil {
        panic(err)
    }
    defer out.Close()

    _, err = io.Copy(out, resp.Body) // 保存到本地文件
    if err != nil {
        panic(err)
    }
}

5. 常见问题

  1. 并发请求
    使用 goroutines 实现并发请求:

    go func(url string) {
        resp, _ := http.Get(url)
        defer resp.Body.Close()
        // 处理响应
    }("https://example.com")
  2. Debug 请求和响应
    利用 net/http/httputil 打印完整信息:

    req, _ := http.NewRequest("GET", "https://example.com", nil)
    dump, _ := httputil.DumpRequestOut(req, true)
    fmt.Println(string(dump))

如果你有具体的功能需求,可以进一步展开讲解!

每日更新-免费小火箭账号
不要错过任何机会,探索最新的应用和游戏,就在我们的平台。
立即访问
最后修改:2025 年 01 月 07 日
如果觉得我的文章对你有用,请随意赞赏