使用Golang编写REST API客户端的实践指南
使用Golang编写REST API客户端的实践指南
package main
import (
"encoding/json"
"fmt"
"net/http"
"time"
)
// Client 结构体用于持有 HTTP 客户端和基础 URL
type Client struct {
HTTPClient *http.Client
BaseURL string
}
// NewClient 创建并返回一个新的 Client 实例
func NewClient(baseURL string) *Client {
return &Client{
HTTPClient: &http.Client{Timeout: 10 * time.Second},
BaseURL: baseURL,
}
}
// GetUser 方法通过 ID 获取用户信息
func (c *Client) GetUser(id string) (*User, error) {
req, err := http.NewRequest("GET", fmt.Sprintf("%s/users/%s", c.BaseURL, id), nil)
if err != nil {
return nil, err
}
resp, err := c.HTTPClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var user User
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
return nil, err
}
return &user, nil
}
// User 结构体表示用户数据模型
type User struct {
ID string `json:"id"`
Name string `json:"name"`
}
func main() {
client := NewClient("https://api.example.com")
user, err := client.GetUser("123")
if err != nil {
fmt.Printf("获取用户时出错: %v\n", err)
return
}
fmt.Printf("用户: %+v\n", user)
}
更多关于使用Golang编写REST API客户端的实践指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于使用Golang编写REST API客户端的实践指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个很好的REST API客户端基础实现。我来补充几个关键实践点:
1. 添加请求头管理和错误处理
func (c *Client) GetUser(id string) (*User, error) {
req, err := http.NewRequest("GET", fmt.Sprintf("%s/users/%s", c.BaseURL, id), nil)
if err != nil {
return nil, fmt.Errorf("创建请求失败: %w", err)
}
// 设置请求头
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
resp, err := c.HTTPClient.Do(req)
if err != nil {
return nil, fmt.Errorf("请求执行失败: %w", err)
}
defer resp.Body.Close()
// 检查HTTP状态码
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("API返回错误: %s, 响应: %s", resp.Status, string(body))
}
var user User
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
return nil, fmt.Errorf("JSON解析失败: %w", err)
}
return &user, nil
}
2. 实现POST请求示例
// CreateUser 创建新用户
func (c *Client) CreateUser(user *User) (*User, error) {
jsonData, err := json.Marshal(user)
if err != nil {
return nil, fmt.Errorf("JSON编码失败: %w", err)
}
req, err := http.NewRequest(
"POST",
fmt.Sprintf("%s/users", c.BaseURL),
bytes.NewBuffer(jsonData),
)
if err != nil {
return nil, fmt.Errorf("创建请求失败: %w", err)
}
req.Header.Set("Content-Type", "application/json")
resp, err := c.HTTPClient.Do(req)
if err != nil {
return nil, fmt.Errorf("请求执行失败: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("创建用户失败: %s, 响应: %s", resp.Status, string(body))
}
var createdUser User
if err := json.NewDecoder(resp.Body).Decode(&createdUser); err != nil {
return nil, fmt.Errorf("JSON解析失败: %w", err)
}
return &createdUser, nil
}
3. 添加重试机制
type Client struct {
HTTPClient *http.Client
BaseURL string
MaxRetries int
}
func (c *Client) doWithRetry(req *http.Request) (*http.Response, error) {
var resp *http.Response
var err error
for i := 0; i <= c.MaxRetries; i++ {
resp, err = c.HTTPClient.Do(req)
if err == nil && resp.StatusCode < 500 {
return resp, nil
}
if i < c.MaxRetries {
time.Sleep(time.Duration(i) * time.Second) // 指数退避
}
}
return resp, err
}
4. 实现请求超时控制
func NewClient(baseURL string) *Client {
return &Client{
HTTPClient: &http.Client{
Timeout: 30 * time.Second,
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
},
},
BaseURL: baseURL,
MaxRetries: 3,
}
}
5. 添加请求日志
type loggingTransport struct {
transport http.RoundTripper
}
func (t *loggingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
start := time.Now()
resp, err := t.transport.RoundTrip(req)
duration := time.Since(start)
fmt.Printf("[%s] %s %s - Duration: %v\n",
time.Now().Format("2006-01-02 15:04:05"),
req.Method,
req.URL.Path,
duration,
)
return resp, err
}
// 在Client中使用
func NewClient(baseURL string) *Client {
return &Client{
HTTPClient: &http.Client{
Timeout: 30 * time.Second,
Transport: &loggingTransport{
transport: http.DefaultTransport,
},
},
BaseURL: baseURL,
}
}
这些实践能显著提升REST API客户端的健壮性和可维护性。

