Gin 真正的核心,不是 Engine,而是你每天都在摸的 *gin.Context。
它像一张“本次车辆处置流转单”,上面挂着:
- 请求本体
- 路径参数
- 查询参数
- 请求头
- 请求体绑定结果
- 中间件之间共享的数据
- 响应写出器
- 错误列表
看一个典型 handler:
func getTicket(c *gin.Context) {
id := c.Param("id")
traceID := c.GetHeader("X-Trace-ID")
c.JSON(http.StatusOK, gin.H{
"id": id,
"trace_id": traceID,
})
}#1. c 里最常用的东西
| 能力 | 作用 |
|---|---|
c.Param("id") |
取路径参数 |
c.Query("q") / c.DefaultQuery(...) |
取查询参数 |
c.GetHeader("Authorization") |
取请求头 |
c.ShouldBindJSON(&x) |
绑定 JSON |
c.Set("userID", v) / c.Get("userID") |
在中间件链里共享数据 |
c.JSON(...) / c.String(...) / c.HTML(...) |
发响应 |
c.Error(err) |
把错误挂进上下文,交给后续统一处理 |
c.Next() / c.Abort() |
控制中间件链继续还是拦停 |
#2. 很多人会混淆的两个“上下文”
Gin 里有两种东西容易被混为一谈:
gin.Context
└── Gin 自己的请求流转单,服务于 HTTP 处理链
c.Request.Context()
└── Go 标准 context.Context,服务于超时、取消、下游 I/O 传播这件事非常重要。
在中间件和 handler 之间传一些业务字段,用 c.Set() / c.Get()。
往数据库、HTTP 客户端、gRPC、下游服务传上下文,用 c.Request.Context()。
别反过来。