上下文
概述
上下文管理机制,基于标准 context.Context 实现框架解耦
上下文管理
Bamboo Base 提供了完整的上下文管理机制,基于标准 context.Context 实现框架解耦。
相关包
| 包 | 别名 | 说明 |
|---|---|---|
.../context | xCtx | 上下文键常量定义 |
.../utility/ctxutil | xCtxUtil | 上下文工具函数 |
.../helper | xHelper | 上下文中间件 |
.../register/node | xRegNode | 节点化注册系统 |
工作原理
上下文数据流
// 1. Register 创建节点管理器
xReg.Register(ctx, nodeList)
│
├── configInit() // 私有:加载配置
├── loggerInit() // 私有:初始化日志
│
// 2. 内置节点注入雪花算法
├── SnowflakeNodeKey → *xSnowflake.Node
│
// 3. 自定义节点注入业务资源
├── DatabaseKey → *gorm.DB
├── RedisClientKey → *redis.Client
│
// 4. 引擎初始化,注入上下文到请求
└── 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:按顺序获取完整节点列表
使用示例
nodeList := xCtx.NewCtxNodeList()
nodeList.Append(xCtx.DatabaseKey, initDatabase())
nodeList.Append(xCtx.RedisClientKey, initRedis())
reg := xReg.Register(ctx, []xRegNode.RegNodeList{
{Key: xCtx.RegNodeKey, Node: func(ctx context.Context) (any, error) {
return nodeList, nil
}},
})注入上下文
方式一:节点化注入(推荐)
在 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() {
reg := xReg.Register(context.Background(), []xRegNode.RegNodeList{
{Key: xCtx.DatabaseKey, Node: initDatabase},
{Key: xCtx.RedisClientKey, Node: initRedis},
})
reg.Serve.Run(":8080")
}
// 数据库初始化节点
func initDatabase(ctx context.Context) (any, error) {
db, err := gorm.Open(...)
return db, err
}
// Redis 初始化节点
func initRedis(ctx context.Context) (any, error) {
rdb := redis.NewClient(...)
return rdb, nil
}方式二:中间件注入
在业务中间件中注入(适用于请求级资源):
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 场景使用(如定时任务、消息队列)