竹简文档
上下文

概述

上下文管理机制,基于标准 context.Context 实现框架解耦

上下文管理

Bamboo Base 提供了完整的上下文管理机制,基于标准 context.Context 实现框架解耦

相关包

别名说明
.../contextxCtx上下文键常量定义
.../utility/ctxutilxCtxUtil上下文工具函数
.../helperxHelper上下文中间件
.../register/nodexRegNode节点化注册系统

工作原理

上下文数据流

初始化流程
// 1. Register 创建节点管理器(v1.0.5 起 opts 作为变参传入)
xReg.Register(ctx, nodeList, opts...)

    ├── configInit()           // 私有:加载配置
    ├── loggerInit()           // 私有:初始化日志

    // 2. 框架保留键:雪花算法(始终注入)
    ├── SnowflakeNodeKey → *xSnowflake.Node

    // 3. 框架保留键:数据库与缓存(来自 opts,启用时注入)
    ├── DatabaseKey      → *gorm.DB          // WithDatabase 启用时
    ├── CacheManagerKey → *xCache.Manager    // WithCache 启用时
    ├── RedisClientKey   → *redis.Client      // Redis 后端时

    // 4. 业务自定义节点(来自 nodeList,键不得与保留键冲突)

    // 5. 引擎初始化,注入上下文到请求
    └── engineInit()
            └── injectContext(ctx)
请求流程
// 5. RequestContext 中间件注入请求级数据
xHelper.RequestContext()
    ├── RequestKey       → UUID 请求标识
    └── UserStartTimeKey → 请求开始时间

快速使用

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

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

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

    // 获取数据库连接(错误返回版本)
    db, err := xCtxUtil.GetDB(ctx)

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

    // 生成雪花 ID
    id := xCtxUtil.MustGenerateSnowflakeID(ctx)

    // 获取请求 ID
    requestID := xCtxUtil.GetRequestKey(ctx)
}

上下文节点

ContextNode 用于在初始化阶段保存上下文中的资源条目,配合 ContextNodeList 形成有序的键值链式列表。

import xCtx "github.com/bamboo-services/bamboo-base-go/defined/context"

ContextNode 结构

type ContextNode struct {
    Key   xCtx.ContextKey
    Value any
}
  • Key:上下文键,用于标识资源类型
  • Value:资源实例,支持任意类型

ContextNodeList 结构

type ContextNodeList []ContextNode

func NewCtxNodeList() ContextNodeList
func (c ContextNodeList) GetList() []ContextNode
func (c ContextNodeList) Get(key ContextKey) any
func (c *ContextNodeList) Append(key ContextKey, value any)

常用能力:

  • Get:按键读取已注入资源
  • Append:追加新的资源节点
  • GetList:按顺序获取完整节点列表

使用示例

register.go
// v1.0.5 起:DatabaseKey / RedisClientKey 由 opts 自动注册,
// 业务侧只需在 nodeList 中放纯业务自定义键
reg := xReg.Register(ctx, []xRegNode.RegNodeList{
    {Key: xCtx.RegNodeKey, Node: func(ctx context.Context) (any, error) {
        return customNodeList, nil
    }},
},
    xOption.WithDatabase(xOptDatabase.FromEnv()), // v1.2.0 起需空白导入对应驱动插件
    xOption.WithCache(xOptCache.FromEnv()),
)

注入上下文

方式一:节点化注入(推荐)

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() {
    // v1.0.5 起:通过 opts 声明式装配,框架自动注册保留键
    reg := xReg.Register(context.Background(), nil,
        xOption.WithDatabase(xOptDatabase.FromEnv()),  // → DatabaseKey(v1.2.0 起需导入对应驱动插件)
        xOption.WithCache(xOptCache.FromEnv()),        // → CacheManagerKey + RedisClientKey
    )

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

DatabaseKey / CacheManagerKey / RedisClientKey / SnowflakeNodeKey框架保留键,由 Register 根据 opts 自动注册,不能在 nodeList 中重复注册。如需注入自定义资源(非框架内置组件),请使用自定义 ContextKey

方式二:中间件注入

在业务中间件中注入(适用于请求级资源):

middleware.go
func InjectUserMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 获取用户信息...
        user := getUserFromToken(c)

        // 注入到 Gin 上下文
        c.Set("user", user)

        c.Next()
    }
}

框架解耦

新版本的核心改进是框架解耦

方面旧设计新设计
工具函数参数*gin.Contextcontext.Context
资源注入Gin 中间件节点化系统
上下文传递c.Set() / c.Get()context.WithValue()
业务代码依赖 Gin可独立测试

优势:

  • ✅ 业务逻辑不再依赖 Gin 框架
  • ✅ 更容易编写单元测试
  • ✅ 支持在非 HTTP 场景使用(如定时任务、消息队列)

下一步

On this page