Skip to content

共享 HTTP 客戶端

概述

clients 包提供了一個線程安全、可重用的 HTTP 客戶端,具有可配置的連接池和連接管理。它採用單例模式確保應用程序中只有一個 HTTP 客戶端實例。

功能特點

  • 連接池:可配置的最大空閒連接數、每個主機的最大連接數
  • TLS 配置:自定義 TLS 設置支持
  • 代理支持:可配置的 HTTP 代理
  • Panic 恢復:內置 panic 處理,防止崩潰
  • 響應解析:通用 JSON 響應解析

HTTPClientConfig

共享 HTTP 客戶端的配置結構。

字段

字段類型默認值描述
MaxIdleConnsint100連接池中的最大空閒連接數
MaxIdleConnsPerHostint10每個主機的最大空閒連接數
MaxConnsPerHostint100每個主機的最大連接數
IdleConnTimeouttime.Duration90s空閒連接超時時間
TLSConfig*tls.ConfignilTLS 配置
CheckRedirectfunc(req *http.Request, via []*http.Request) errornil重定向策略
Proxyfunc(*http.Request) (*url.URL, error)nil代理配置
DisableKeepAlivesboolfalse禁用 HTTP keep-alives
DisableCompressionboolfalse禁用壓縮
ForceAttemptHTTP2booltrue強制使用 HTTP/2

API 參考

InitDefaultSharedHTTPClient()

使用默認配置初始化共享 HTTP 客戶端。

go
clients.InitDefaultSharedHTTPClient()

InitSharedHTTPClientWithConfig(config *HTTPClientConfig)

使用自定義配置初始化共享 HTTP 客戶端。由於採用單例模式,此函數只能調用一次。

go
config := &clients.HTTPClientConfig{
    MaxIdleConns:        200,
    MaxIdleConnsPerHost: 20,
    MaxConnsPerHost:     200,
    IdleConnTimeout:     60 * time.Second,
}
clients.InitSharedHTTPClientWithConfig(config)

Request(req *http.Request) (data []byte, headers http.Header, httpCode int, err error)

使用共享客戶端執行 HTTP 請求。返回響應體、響應頭、狀態碼和任何錯誤。

go
req, _ := http.NewRequest("GET", "https://api.example.com/data", nil)
data, headers, code, err := clients.Request(req)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Status: %d, Body: %s\n", code, string(data))

ParseResponse[T any](data []byte, dest *T) error

將 JSON 響應數據解析為類型化結構體。

go
type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

var user User
err := clients.ParseResponse(data, &user)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("User: %s <%s>\n", user.Name, user.Email)

示例

go
package main

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

	"github.com/leoheung/go-patterns/net/clients"
)

func main() {
	// 1. 初始化共享 HTTP 客戶端
	clients.InitDefaultSharedHTTPClient()

	// 2. 創建帶有超時的請求(通過 context)
	req, _ := http.NewRequest("GET", "https://api.example.com/users/1", nil)
	req = req.WithContext(req.Context())

	// 3. 執行請求
	data, headers, statusCode, err := clients.Request(req)
	if err != nil {
		fmt.Printf("錯誤: %v\n", err)
		return
	}

	// 4. 處理響應
	fmt.Printf("狀態碼: %d\n", statusCode)
	fmt.Printf("Content-Type: %s\n", headers.Get("Content-Type"))
	fmt.Printf("響應體: %s\n", string(data))
}

注意事項

  • 共享 HTTP 客戶端使用 sync.Once 確保只初始化一次
  • 超時應該通過請求級別的 context 控制,而不是客戶端級別的超時
  • 響應體在讀取後會自動關閉
  • 內置 panic 恢復機制,防止請求失敗導致應用程序崩潰
  • 連接池可顯著提高對同一主機的多次請求的性能

Released under the MIT License.