
本文详解如何使用 go 标准库 `net/http` 发起类似 curl 的 http 请求,重点支持 get/post 等方法携带 json 字符串或结构体作为请求体(即等效于 curl 的 `-d` 参数),无需依赖第三方 sdk。
在 Go 中模拟 curl -XGET ... -d '{...}' 的核心在于:*手动构造 `http.Request,将 JSON 数据作为请求体(body)传入,并显式设置Content-Type: application/json`**。虽然 HTTP 规范中 GET 请求通常不携带 body(且部分服务端可能忽略),但如 Elasticsearch 等 RESTful API 明确支持 GET + JSON body 语义(用于搜索等场景),因此完全可行。
以下是以你提供的 Elasticsearch 示例为基础的完整实现:
package main
import (
"bytes"
"fmt"
"io"
"net/http"
"strings"
)
func main() {
// 构造 JSON 查询体(字符串形式)
jsonBody := `{
"query": {
"term": { "user": "kimchy" }
}
}`
// 创建 HTTP 请求:GET 方法 + JSON body
req, err := http.NewRequest("GET", "http://localhost:9200/twitter/tweet/_search", strings.NewReader(jsonBody))
if err != nil {
panic(err)
}
// 关键:设置 Content-Type 头,告知服务端这是 JSON 数据
req.Header.Set("Content-Type", "application/json")
// 可选:设置 User-Agent(某些服务端会校验)
req.Header.Set("User-Agent", "Go-ES-Client/1.0")
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// 读取响应
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Printf("Status: %s\n", resp.Status)
fmt.Printf("Response: %s\n", string(body))
}✅ 关键要点说明:http.NewRequest(method, url, bodyReader) 是构造自定义请求的核心函数,bodyReader 可为 strings.NewReader(jsonStr)、bytes.NewReader([]byte{...}) 或任意 io.Reader;必须手动调用 req.Header.Set("Content-Type", "application/json"),否则服务端可能无法正确解析 JSON;对于结构体,可先用 json.Marshal() 序列化: type SearchQuery struct { Query struct { Term map[string]string `json:"term"` } `json:"query"` } data := SearchQuery{Query: struct{ Term map[string]string }{Term: map[string]string{"user": "kimchy"}}} jsonBytes, _ := json.Marshal(data) req, _ := http.NewRequest("GET", url, bytes.NewReader(jsonBytes))
⚠️ 注意事项:
- 虽然 RFC 7231 允许 GET 请求携带 body,但并非所有中间件、代理或 Web 框架都支持解析它。若遇到 400 或无响应,建议改用 POST(Elasticsearch 同样支持 POST /_search);
- 生产环境建议添加超时控制:
client := &http.Client{ Timeout: 10 * time.Second, } - 如需复用连接、管理 Cookie 或设置 TLS 配置,请自定义 http.Transport。
掌握 http.NewRequest + io.Reader + Header 设置这一组合,即可灵活模拟任意 curl 命令(包括 -XPUT, -H "Authorization: ...", -d @file.json 等),是构建 Go HTTP 客户端的基石能力。










