net/http 可构建轻量 REST 服务:需手动精确匹配路径、解析 URL 参数、一次性读取 Body、导出结构体字段并加 json tag、校验 Content-Type、用 http.Error 或封装函数返回错误、显式处理 OPTIONS 预检并设置 CORS 头。

用 net/http 启动最简 REST 服务,别急着上框架
Go 原生 net/http 完全够用,尤其在中小规模 API 场景。过早引入 gin 或 echo 反而掩盖路由匹配、中间件执行顺序等关键细节。
-
http.HandleFunc注册路径时,前缀匹配是隐式的:注册/api/users会同时响应/api/users/123—— 需手动检查r.URL.Path是否精确匹配 - 使用
http.ServeMux自定义路由时,注意它不支持路径参数(如/users/{id}),必须自己解析r.URL.Path并提取id - 启动服务务必显式指定端口和错误处理:
if err := http.ListenAndServe(":8080", nil); err != nil && err != http.ErrServerClosed { log.Fatal(err) }
正确解析 JSON 请求体,避免 io.EOF 和空结构体
常见错误是直接对 http.Request.Body 多次调用 json.Unmarshal —— Body 是单次读取流,第二次读就会返回 io.EOF。
- 始终用
io.ReadAll(r.Body)一次性读完,再传给json.Unmarshal;不要试图复用r.Body - 结构体字段必须首字母大写且带
jsontag,否则反序列化后字段为空:type User struct { Name string `json:"name"` } - 用
r.Header.Get("Content-Type")检查是否为application/json,非 JSON 请求应返回415 Unsupported Media Type
用 http.Error 统一返回错误,别拼接字符串
手写 w.WriteHeader(400); w.Write([]byte(`{"error":"xxx"}`)) 容易遗漏状态码、Content-Type 或格式不一致。
- 优先用
http.Error(w, "bad request", http.StatusBadRequest),它自动设状态码和text/plain类型 - 若需返回 JSON 错误,单独封装函数:
func writeJSONError(w http.ResponseWriter, msg string, code int) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) json.NewEncoder(w).Encode(map[string]string{"error": msg}) } - 注意
http.Error不会终止 handler 执行,后续代码仍会运行,必要时加return
处理 CORS 时,OPTIONS 预检请求必须显式响应
浏览器发跨域请求前会先发 OPTIONS,如果没处理,前端卡在 pending 状态,控制台只显示 “CORS error”。
立即学习“go语言免费学习笔记(深入)”;
- 在 handler 开头判断:
if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK); return } - 必须设置以下响应头:
Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers - 如果允许携带 cookie,还需加
Access-Control-Allow-Credentials: true,且Allow-Origin不能为*










