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. 最佳实践
- 重用客户端: 避免为每个请求创建新客户端
- 设置超时: 防止请求挂起
- 关闭响应体: 使用
defer确保关闭 - 错误处理: 检查每个可能出错的地方
- 连接池: 使用
Transport配置优化连接 - 重试机制: 对临时错误实现重试逻辑
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请求流程,包括数据准备、请求创建、客户端配置、请求发送、响应处理和错误处理。

浙公网安备 33010602011771号