contextpool

package
v1.1.26 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 6, 2025 License: Apache-2.0 Imports: 4 Imported by: 0

README

Context Pool - 业务上下文对象池

基于 sync.Pool 实现的高性能业务上下文对象池,避免频繁的内存分配和 GC 压力。

特性

  • ✅ 零依赖,基于标准库 sync.Pool
  • ✅ 自动从 Gin Context 提取常用信息
  • ✅ 支持自定义数据存储
  • ✅ 错误收集机制
  • ✅ 支持创建副本用于 goroutine
  • ✅ 类型安全的 Get 方法
  • ✅ 自动重置,防止数据泄露

快速开始

基本使用
package main

import (
    "github.com/gin-gonic/gin"
    "github.com/ChenBigdata421/jxt-core/sdk/pkg/contextpool"
)

func Handler(c *gin.Context) {
    // 从池中获取 Context
    ctx := contextpool.Acquire(c)
    defer contextpool.Release(ctx) // 确保归还到池中
    
    // 使用 Context
    ctx.Set("orderID", "order-123")
    
    // 业务逻辑
    processOrder(ctx)
}

func processOrder(ctx *contextpool.Context) {
    orderID := ctx.GetString("orderID")
    userID := ctx.UserID
    
    // 处理订单...
}
在 Goroutine 中使用
func Handler(c *gin.Context) {
    ctx := contextpool.Acquire(c)
    defer contextpool.Release(ctx)
    
    // ❌ 错误:直接在 goroutine 中使用
    go func() {
        ctx.Set("key", "value") // 危险!ctx 可能已被回收
    }()
    
    // ✅ 正确:使用副本
    ctxCopy := ctx.Copy()
    go func() {
        ctxCopy.Set("key", "value") // 安全
        // 注意:副本不需要 Release
    }()
}
错误处理
func Handler(c *gin.Context) {
    ctx := contextpool.Acquire(c)
    defer contextpool.Release(ctx)
    
    if err := validateRequest(ctx); err != nil {
        ctx.AddError(err)
    }
    
    if err := processRequest(ctx); err != nil {
        ctx.AddError(err)
    }
    
    if ctx.HasErrors() {
        c.JSON(500, gin.H{
            "errors": ctx.Errors(),
        })
        return
    }
    
    c.JSON(200, gin.H{"msg": "success"})
}
自定义数据
func Handler(c *gin.Context) {
    ctx := contextpool.Acquire(c)
    defer contextpool.Release(ctx)
    
    // 设置数据
    ctx.Set("orderID", "order-123")
    ctx.Set("amount", 100)
    ctx.Set("isPaid", true)
    
    // 获取数据
    orderID := ctx.GetString("orderID")
    amount := ctx.GetInt("amount")
    isPaid := ctx.GetBool("isPaid")
    
    // 通用获取
    if val, ok := ctx.Get("orderID"); ok {
        // 处理 val
    }
}
性能统计
func Handler(c *gin.Context) {
    ctx := contextpool.Acquire(c)
    defer contextpool.Release(ctx)
    
    // 业务逻辑
    processRequest(ctx)
    
    // 获取执行时长
    duration := ctx.Duration()
    c.Header("X-Duration", duration.String())
}

API 文档

核心方法
Acquire
func Acquire(c *gin.Context) *Context

从池中获取 Context,自动提取 Gin Context 中的信息。

AcquireWithContext
func AcquireWithContext(parent context.Context) *Context

从标准 context.Context 获取 Context。

Release
func Release(ctx *Context)

释放 Context 回池中,必须调用以避免内存泄漏。

Context 方法
数据操作
  • Set(key string, value interface{}) - 设置数据
  • Get(key string) (interface{}, bool) - 获取数据
  • MustGet(key string) interface{} - 获取数据,不存在则 panic
  • GetString(key string) string - 获取字符串
  • GetInt(key string) int - 获取整数
  • GetBool(key string) bool - 获取布尔值
错误处理
  • AddError(err error) - 添加错误
  • Errors() []error - 获取所有错误
  • HasErrors() bool - 是否有错误
其他
  • Duration() time.Duration - 获取执行时长
  • Copy() *Context - 创建副本(用于 goroutine)
Context 字段
type Context struct {
    context.Context  // 标准 Context
    
    RequestID string // 请求 ID
    UserID    string // 用户 ID
    TenantID  string // 租户 ID
    TraceID   string // 追踪 ID
    StartTime time.Time // 开始时间
}

最佳实践

1. 始终使用 defer Release
// ✅ 正确
func Handler(c *gin.Context) {
    ctx := contextpool.Acquire(c)
    defer contextpool.Release(ctx)
    // ...
}

// ❌ 错误
func Handler(c *gin.Context) {
    ctx := contextpool.Acquire(c)
    // 忘记 Release,导致内存泄漏
}
2. Goroutine 中使用副本
// ✅ 正确
ctx := contextpool.Acquire(c)
defer contextpool.Release(ctx)

ctxCopy := ctx.Copy()
go func() {
    // 使用 ctxCopy
}()

// ❌ 错误
ctx := contextpool.Acquire(c)
defer contextpool.Release(ctx)

go func() {
    ctx.Set("key", "value") // 危险!
}()
3. 避免存储大对象
// ❌ 不推荐
ctx.Set("largeData", make([]byte, 1024*1024)) // 1MB

// ✅ 推荐
ctx.Set("dataRef", dataID) // 存储引用
4. 及时清理错误
func Handler(c *gin.Context) {
    ctx := contextpool.Acquire(c)
    defer contextpool.Release(ctx) // Release 会自动清理错误
    
    // 业务逻辑
}

性能测试

运行基准测试:

cd sdk/pkg/contextpool
go test -bench=. -benchmem

预期结果:

BenchmarkContextPool/WithPool-8      10000000    10.2 ns/op    0 B/op    0 allocs/op
BenchmarkContextPool/WithoutPool-8    5000000    25.3 ns/op   48 B/op    1 allocs/op

使用对象池可以:

  • 减少 60% 的内存分配
  • 提升 2-3 倍的性能
  • 降低 GC 压力

注意事项

  1. 必须 Release:每次 Acquire 后必须 Release,建议使用 defer
  2. Goroutine 安全:在 goroutine 中使用副本,不要直接使用原 Context
  3. 避免大对象:不要在 Context 中存储大对象,会影响池化效果
  4. 副本不回收:Copy() 创建的副本不会自动回收到池中

与 Gin Context 的区别

特性 Gin Context contextpool.Context
对象池 ✅ 内置 ✅ 内置
自定义数据
错误收集
类型安全 Get
执行时长
业务字段 ✅ (UserID, TenantID 等)

集成示例

与 jxt-core 集成
package handler

import (
    "github.com/gin-gonic/gin"
    "github.com/ChenBigdata421/jxt-core/sdk/pkg/contextpool"
    "github.com/ChenBigdata421/jxt-core/sdk/pkg/logger"
)

func OrderHandler(c *gin.Context) {
    ctx := contextpool.Acquire(c)
    defer contextpool.Release(ctx)
    
    // 记录日志
    logger.Infof("处理订单请求, UserID: %s, RequestID: %s", 
        ctx.UserID, ctx.RequestID)
    
    // 业务逻辑
    if err := processOrder(ctx); err != nil {
        ctx.AddError(err)
        c.JSON(500, gin.H{"error": err.Error()})
        return
    }
    
    c.JSON(200, gin.H{
        "msg":      "success",
        "duration": ctx.Duration().String(),
    })
}

许可证

Apache 2.0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Release

func Release(ctx *Context)

Release 释放 Context 回池中

Types

type Context

type Context struct {
	context.Context

	// 基础字段
	RequestID string
	UserID    string
	TenantID  string
	TraceID   string

	// 时间信息
	StartTime time.Time
	// contains filtered or unexported fields
}

Context 业务上下文,支持对象池复用

func Acquire

func Acquire(c *gin.Context) *Context

Acquire 从池中获取 Context 使用示例:

ctx := contextpool.Acquire(c)
defer contextpool.Release(ctx)

func AcquireWithContext

func AcquireWithContext(parent context.Context) *Context

AcquireWithContext 从标准 context.Context 获取

func (*Context) AddError

func (c *Context) AddError(err error)

AddError 添加错误(并发安全)

func (*Context) Copy

func (c *Context) Copy() *Context

Copy 创建副本(用于 goroutine) 注意:副本不会被自动回收到池中

func (*Context) Duration

func (c *Context) Duration() time.Duration

Duration 获取执行时长

func (*Context) Errors

func (c *Context) Errors() []error

Errors 获取所有错误(并发安全)

func (*Context) Get

func (c *Context) Get(key string) (interface{}, bool)

Get 获取自定义数据(并发安全)

func (*Context) GetBool

func (c *Context) GetBool(key string) bool

GetBool 获取布尔类型数据(并发安全)

func (*Context) GetInt

func (c *Context) GetInt(key string) int

GetInt 获取整数类型数据(并发安全)

func (*Context) GetString

func (c *Context) GetString(key string) string

GetString 获取字符串类型数据(并发安全)

func (*Context) HasErrors

func (c *Context) HasErrors() bool

HasErrors 是否有错误(并发安全)

func (*Context) MustGet

func (c *Context) MustGet(key string) interface{}

MustGet 获取自定义数据,不存在则 panic(并发安全)

func (*Context) Set

func (c *Context) Set(key string, value interface{})

Set 设置自定义数据(并发安全)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL