竹简文档
初始化

上下文注入

通过节点化系统和中间件实现上下文资源注入

上下文注入

新版本采用节点化系统实现上下文资源注入,取代了原有的 SystemContextInit 方法。

注入机制

节点化注入(初始化时)

Register 时通过自定义节点注入全局资源:

main.go
import (
    "context"
    xCtx "github.com/bamboo-services/bamboo-base-go/defined/context"
    xReg "github.com/bamboo-services/bamboo-base-go/major/register"
    xRegNode "github.com/bamboo-services/bamboo-base-go/major/register/node"
)

func main() {
    reg := xReg.Register(context.Background(), []xRegNode.RegNodeList{
        {Key: xCtx.DatabaseKey, Node: initDatabase},
        {Key: xCtx.RedisClientKey, Node: initRedis},
    })

    reg.Serve.Run(":8080")
}

中间件注入(请求时)

xHelper.RequestContext() 中间件为每个请求注入请求级数据:

helper/request_context.go
func RequestContext() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 生成请求唯一标识
        requestID := uuid.New().String()

        // 记录请求开始时间
        startTime := time.Now()

        // 注入到上下文
        ctx := c.Request.Context()
        ctx = context.WithValue(ctx, xCtx.RequestKey, requestID)
        ctx = context.WithValue(ctx, xCtx.UserStartTimeKey, startTime)
        c.Request = c.Request.WithContext(ctx)

        c.Next()
    }
}

上下文合并

injectContext 中间件将初始化上下文合并到每个请求:

register_gin.go
func injectContext(ctx context.Context) func(c *gin.Context) {
    return func(c *gin.Context) {
        // 将初始化上下文(包含 DB、Redis、Snowflake 等)注入到请求
        c.Request = c.Request.WithContext(ctx)
        c.Next()
    }
}

注入的资源

资源Key类型注入时机
雪花算法节点SnowflakeNodeKey*xSnowflake.Node内置节点(自动)
数据库连接DatabaseKey*gorm.DB自定义节点
Redis 客户端RedisClientKey*redis.Client自定义节点
请求 IDRequestKeystring请求中间件
开始时间UserStartTimeKeytime.Time请求中间件

获取上下文资源

使用 xCtxUtil 包从上下文获取注入的资源:

import xCtxUtil "github.com/bamboo-services/bamboo-base-go/common/utility/context"

func CreateOrder(c *gin.Context) {
    // 获取标准上下文
    ctx := c.Request.Context()

    // 获取数据库连接
    db := xCtxUtil.MustGetDB(ctx)

    // 获取 Redis 客户端
    rdb := xCtxUtil.MustGetRDB(ctx)

    // 获取雪花算法节点
    node := xCtxUtil.GetSnowflakeNode(ctx)

    // 生成订单 ID
    orderID := node.MustGenerate(xSnowflake.GeneOrder)
}

自定义初始化节点

创建自定义初始化节点的标准模式:

init_database.go
import (
    "context"
    xLog "github.com/bamboo-services/bamboo-base-go/common/log"
)

// 初始化节点函数签名:func(ctx context.Context) (any, error)
func initDatabase(ctx context.Context) (any, error) {
    log := xLog.WithName(xLog.NamedINIT)
    log.Info(ctx, "初始化数据库连接")

    // 构建 DSN
    dsn := buildDSN()

    // 创建数据库连接
    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
        return nil, err
    }

    log.Info(ctx, "数据库连接成功")

    // 返回值将被存入上下文
    return db, nil
}

请求 ID

每个请求都会自动生成唯一的请求 ID:

func GetRequestID(c *gin.Context) string {
    return xCtxUtil.GetRequestKey(c.Request.Context())
}

请求 ID 会:

  • 存储在上下文中,通过 xCtx.RequestKey 访问
  • 添加到响应头 X-Request-ID
  • 用于日志追踪和问题排查

迁移指南

从旧版本迁移:

旧版本新版本
xReg.SystemContextInit()节点化系统自动处理
c.Set(key, value)context.WithValue()
c.Get(key)ctx.Value(key)
xCtxUtil.GetDB(c)xCtxUtil.MustGetDB(c.Request.Context())

下一步

On this page