Go中HTTP收发核心是服务端(http.ServeMux+ListenAndServe)与客户端(http.Client+NewRequest)分工:服务端用HandleFunc注册处理器,响应JSON等;客户端需自定义Client设超时,正确处理Body读写与关闭。

在 Go 中用 net/http 发送和接收 HTTP 数据非常直接,核心在于理解服务端(http.ServeMux + http.ListenAndServe)和客户端(http.Client + http.NewRequest)两种角色的分工。
接收请求:写一个简单的 HTTP 服务
服务端主要靠注册处理器函数来响应不同路径的请求。Go 内置的 http.HandleFunc 是最简方式:
- 它自动帮你把路径和函数绑定,并处理底层连接、解析请求头/体等细节
- 处理器函数签名固定为
func(http.ResponseWriter, *http.Request) -
http.ResponseWriter用于写响应状态码、头、正文;*http.Request包含所有请求信息(URL、Method、Header、Body、Form 等)
示例:启动一个返回 JSON 的 /api/user 接口
package mainimport ( "encoding/json" "net/http" )
type User struct { ID int
json:"id"Name stringjson:"name"}func userHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(User{ID: 123, Name: "Alice"}) }
func main() { http.HandleFunc("/api/user", userHandler) http.ListenAndServe(":8080", nil) // 启动服务器 }
读取请求数据:表单、JSON、查询参数和原始 Body
根据前端传来的数据格式,选择对应方式解析:
立即学习“go语言免费学习笔记(深入)”;
-
查询参数(URL 中 ?key=value):用
r.URL.Query().Get("key")或r.FormValue("key")(后者会自动调用ParseForm) -
表单数据(application/x-www-form-urlencoded):先调用
r.ParseForm(),再用r.PostFormValue("field") -
JSON 请求体:用
json.NewDecoder(r.Body).Decode(&v),注意r.Body只能读一次,需提前检查Content-Type -
原始字节流(如文件上传、自定义协议):用
io.ReadAll(r.Body),记得关闭或 deferr.Body.Close()
发送请求:用 http.Client 控制超时和重试
不要直接用 http.Get 这类快捷函数——它们用默认 client,无法设超时,容易阻塞。推荐显式创建带配置的 http.Client:
- 设置
Timeout防止请求无限挂起(例如网络故障时) - 可选配
Transport控制连接复用、TLS 设置、代理等 - 用
http.NewRequest构造请求,手动设置 Header、Body(比如加 Authorization、发 JSON)
示例:POST 一个 JSON 到远程 API
client := &http.Client{
Timeout: 5 * time.Second,
}
req, _ := http.NewRequest("POST", "https://api.example.com/data", strings.NewReader(`{"name":"Bob"}`))
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Printf("Status: %s, Body: %s", resp.Status, string(body))
常见陷阱与建议
-
http.Request.Body是io.ReadCloser,必须Close(),否则连接不释放,可能耗尽资源 - 用
http.Error(w, msg, code)快速返回错误响应,比手动写状态码更安全 - 避免在 handler 中启协程处理耗时任务后直接返回——要确保响应已写出,否则客户端收不到
- 生产环境别用
nil作为http.ListenAndServe的第二个参数,应传入自定义http.ServeMux或http.Handler方便测试和扩展










