主题
07 · 标准库:HTTP 与 JSON
目标:不引入 Gin/Echo,先用标准库做出可读的迷你 API。
官方:net/http·encoding/json· Writing Web Applications(经典长文,可扫)
1. 为什么入门坚持标准库
| 做法 | 结果 |
|---|---|
| 第一周上 Gin + ORM + 一整套分层 | 学的是框架,不是 Go |
先 net/http + json | 以后换框架只是路由糖 |
暑假计划也写了:初期先标准库。框架放到能讲清 Handler 签名之后。
2. JSON:结构体标签
go
type Note struct {
ID string `json:"id"`
Content string `json:"content"`
}
func decodeNote(r io.Reader) (Note, error) {
var n Note
dec := json.NewDecoder(r)
if err := dec.Decode(&n); err != nil {
return Note{}, err
}
return n, nil
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
要点:
- 导出字段才能被默认编解码
json:"-"忽略;omitempty省略空值- 未知字段默认忽略;可用
DisallowUnknownFields变严 - 文档与 Example:https://pkg.go.dev/encoding/json
AI 坑:捏造不存在的 tag;或用 map[string]any 却不做类型断言。
3. HTTP Server 最小骨架
go
package main
import (
"encoding/json"
"log"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("ok"))
})
mux.HandleFunc("POST /notes", createNote)
log.Println("listen :8080")
log.Fatal(http.ListenAndServe(":8080", mux))
}
func createNote(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
var n Note
if err := json.NewDecoder(r.Body).Decode(&n); err != nil {
http.Error(w, "bad json", http.StatusBadRequest)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(n)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
说明:
- Go 1.22+ 的
ServeMux支持方法与路径模式(详见net/http文档)。若版本较旧,用手动r.Method判断。 - Handler 签名:
func(http.ResponseWriter, *http.Request) - 中间件 = 包一层
http.Handler(自己写 log wrapper 即可)
4. 客户端也要会
go
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
// http.DefaultClient.Do(req)1
2
3
4
2
3
4
把第 06 篇的 context 接到 HTTP 上。
5. 对照 Koa/Express
| Koa | net/http |
|---|---|
router.get | mux.HandleFunc / Handle |
ctx.body = | json.NewEncoder(w).Encode |
| middleware 链 | 装饰 http.Handler |
ctx.throw(400) | http.Error / 自己写 JSON 错误体 |
6. 练习(为第 10 篇铺路)
实现内存版:
GET /notes→ 列表 JSONPOST /notes→ 创建GET /notes/{id}→ 单条(1.22+ 路径值见文档)
先不要数据库。错误返回统一 JSON:{"error":"..."}。
7. AI 审查提示词
text
技术约束:Go 标准库 only,net/http + encoding/json。
请审查:状态码是否合理、Body 是否关闭、Content-Type、
错误路径是否泄漏内部 err、是否使用 NewDecoder 流式解码。
对照 pkg.go.dev 指出可改进点。1
2
3
4
2
3
4
8. 验收清单
- [ ] 本地
ListenAndServe能 curl 通 - [ ] 会
Encode/Decode结构体 - [ ] 知道 Handler 签名与中间件本质
- [ ] 客户端请求带 context 超时
