Gin Context值存储与检索
Context提供了请求范围内的数据存储机制,用于中间件与处理器间传递数据。
基本存储操作
Set/Get方法
Go
// 存储值
func (c *Context) Set(key string, value any)
// 获取值
func (c *Context) Get(key string) (value any, exists bool)
// 获取值(无类型断言版本)
func (c *Context) MustGet(key string) any
使用示例
Go
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
user, err := validateToken(token)
if err != nil {
c.AbortWithStatus(401)
return
}
// 存储用户信息
c.Set("userID", user.ID)
c.Set("userRole", user.Role)
c.Set("user", user)
c.Next()
}
}
func handler(c *gin.Context) {
// 获取值
userID, exists := c.Get("userID")
if !exists {
c.JSON(500, gin.H{"error": "user not found in context"})
return
}
// 类型断言
id := userID.(uint64)
c.JSON(200, gin.H{"userID": id})
}
类型安全的访问器
自定义类型键
Go
type contextKey string
const (
UserIDKey contextKey = "userID"
UserKey contextKey = "user"
TraceIDKey contextKey = "traceID"
)
func SetUser(c *gin.Context, user *User) {
c.Set(string(UserKey), user)
}
func GetUser(c *gin.Context) (*User, bool) {
val, exists := c.Get(string(UserKey))
if !exists {
return nil, false
}
user, ok := val.(*User)
return user, ok
}
泛型封装(Go 1.18+)
Go
func GetTyped[T any](c *gin.Context, key string) (T, bool) {
val, exists := c.Get(key)
if !exists {
var zero T
return zero, false
}
result, ok := val.(T)
return result, ok
}
// 使用
userID, ok := GetTyped[uint64](c, "userID")
Keys内部实现
Go
type Context struct {
// ...
Keys map[string]any
}
func (c *Context) Set(key string, value any) {
if c.Keys == nil {
c.Keys = make(map[string]any)
}
c.Keys[key] = value
}
func (c *Context) Get(key string) (value any, exists bool) {
if c.Keys == nil {
return nil, false
}
value, exists = c.Keys[key]
return
}
常用存储场景
| 场景 | Key | Value |
|---|---|---|
| 用户认证 | "userID" | uint64 |
| 请求追踪 | "traceID" | string |
| 权限信息 | "permissions" | []string |
| 请求开始时间 | "startTime" | time.Time |
| 自定义数据 | 任意string | any |
批量获取
Go
func GetAllContextValues(c *gin.Context) gin.H {
result := gin.H{}
for key, value := range c.Keys {
result[key] = value
}
return result
}
标准库Context值传递
Go
// Gin Context与标准库Context结合
func middleware(c *gin.Context) {
ctx := context.WithValue(c.Request.Context(), "traceID", "12345")
c.Request = c.Request.WithContext(ctx)
// 同时存储到Gin Context
c.Set("traceID", "12345")
c.Next()
}
// 获取标准库Context中的值
func handler(c *gin.Context) {
traceID := c.Request.Context().Value("traceID")
c.JSON(200, gin.H{"traceID": traceID})
}
注意:Context值仅用于请求范围数据传递,不要存储大量数据,Keys map在请求结束后会清空。
要点总结
- Set/Get实现请求范围内的键值存储
- Keys是map[string]any类型,惰性初始化
- 获取值后需要类型断言转换
- 推荐使用自定义类型键避免冲突
- 不应存储大量数据,仅传递请求元信息
📝 发现内容有误?点击此处直接编辑