上下文
概述
上下文管理机制,基于标准 context.Context 实现框架解耦
上下文管理
Bamboo Base 提供了完整的上下文管理机制,基于标准 context.Context 实现框架解耦。
相关包
| 包 | 别名 | 说明 |
|---|---|---|
.../context | xCtx | 上下文键常量定义 |
.../utility/ctxutil | xCtxUtil | 上下文工具函数 |
.../helper | xHelper | 上下文中间件 |
.../register/node | xRegNode | 节点化注册系统 |
工作原理
上下文数据流
// 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:按顺序获取完整节点列表
使用示例
// 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 时通过自定义节点注入:
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。
方式二:中间件注入
在业务中间件中注入(适用于请求级资源):
func InjectUserMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 获取用户信息...
user := getUserFromToken(c)
// 注入到 Gin 上下文
c.Set("user", user)
c.Next()
}
}框架解耦
新版本的核心改进是框架解耦:
| 方面 | 旧设计 | 新设计 |
|---|---|---|
| 工具函数参数 | *gin.Context | context.Context |
| 资源注入 | Gin 中间件 | 节点化系统 |
| 上下文传递 | c.Set() / c.Get() | context.WithValue() |
| 业务代码 | 依赖 Gin | 可独立测试 |
优势:
- ✅ 业务逻辑不再依赖 Gin 框架
- ✅ 更容易编写单元测试
- ✅ 支持在非 HTTP 场景使用(如定时任务、消息队列)