上下文
自定义注入
扩展上下文,通过节点化系统注入业务自定义数据
自定义注入
除了框架预定义的上下文键,你可以通过节点化系统扩展自定义的业务上下文键。
定义自定义键
在业务项目中创建自定义上下文键常量:
package bContext
import xCtx "github.com/bamboo-services/bamboo-base-go/defined/context"
const (
// 使用 xCtx.ContextKey 类型定义自定义键
TencentCloudForSmsKey xCtx.ContextKey = "business_tencent_cloud_sms" // 腾讯云短信
UserEntityKey xCtx.ContextKey = "business_user_entity" // 用户实体
MerchantEntityKey xCtx.ContextKey = "business_merchant_entity" // 商户实体
)命名规范:
| 前缀 | 说明 | 示例 |
|---|---|---|
context_ | 框架预定义键 | context_database |
business_ | 业务自定义键 | business_user_entity |
注入自定义数据
方式一:节点化注入(推荐)
在 Register 时通过自定义节点注入全局资源:
package main
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"
bContext "your-project/internal/constant/context"
)
func main() {
reg := xReg.Register(context.Background(), []xRegNode.RegNodeList{
// 框架资源
{Key: xCtx.DatabaseKey, Node: initDatabase},
{Key: xCtx.RedisClientKey, Node: initRedis},
// 业务资源
{Key: bContext.TencentCloudForSmsKey, Node: initTencentSms},
})
reg.Serve.Run(":8080")
}
// 腾讯云短信初始化节点
func initTencentSms(ctx context.Context) (any, error) {
credential := common.NewCredential(secretId, secretKey)
client, err := sms.NewClient(credential, "ap-guangzhou", profile.NewClientProfile())
return client, err
}方式二:中间件注入
在认证中间件中注入用户实体(请求级资源):
package middleware
import (
"context"
xError "github.com/bamboo-services/bamboo-base-go/common/error"
xResult "github.com/bamboo-services/bamboo-base-go/major/result"
xCtxUtil "github.com/bamboo-services/bamboo-base-go/common/utility/context"
"github.com/gin-gonic/gin"
bContext "your-project/internal/constant/context"
"your-project/internal/logic"
)
func AuthRequired(c *gin.Context) {
// ... 验证 token 逻辑 ...
// 获取用户信息
ctx := c.Request.Context()
db := xCtxUtil.MustGetDB(ctx)
user, xErr := logic.NewUser(db).GetUser(ctx, userID)
if xErr != nil {
xResult.AbortError(c, xErr.ErrorCode, xErr.ErrorMessage, nil)
return
}
// 注入用户实体到上下文
ctx = context.WithValue(ctx, bContext.UserEntityKey, user)
c.Request = c.Request.WithContext(ctx)
c.Next()
}获取自定义数据
创建工具函数
为自定义键创建便捷的获取函数:
package bCtxUtil
import (
"context"
bContext "your-project/internal/constant/context"
"your-project/internal/entity"
)
// GetUserEntity 从上下文获取当前登录用户
func GetUserEntity(ctx context.Context) *entity.User {
if value := ctx.Value(bContext.UserEntityKey); value != nil {
return value.(*entity.User)
}
return nil
}
// MustGetUserEntity 从上下文获取当前登录用户(不存在则 panic)
func MustGetUserEntity(ctx context.Context) *entity.User {
user := GetUserEntity(ctx)
if user == nil {
panic("用户实体不存在于上下文中")
}
return user
}在 Handler 中使用
package handler
import (
xResult "github.com/bamboo-services/bamboo-base-go/major/result"
"github.com/gin-gonic/gin"
bCtxUtil "your-project/pkg/ctx"
)
func (h *UserHandler) GetProfile(c *gin.Context) {
// 获取当前登录用户
user := bCtxUtil.GetUserEntity(c.Request.Context())
xResult.SuccessHasData(c, "获取成功", user)
}
func (h *UserHandler) UpdateProfile(c *gin.Context) {
// 获取当前登录用户 ID
currentUser := bCtxUtil.MustGetUserEntity(c.Request.Context())
// 更新逻辑...
h.service.UpdateUser(c.Request.Context(), currentUser.ID, req)
xResult.Success(c, "更新成功")
}完整示例
项目结构
your-project/
├── main.go # 入口,注册节点
├── internal/
│ ├── app/
│ │ └── middleware/
│ │ └── auth_required.go # 认证中间件
│ ├── constant/
│ │ └── context/
│ │ └── business.go # 自定义键定义
│ └── handler/
│ └── user.go
└── pkg/
└── ctx/
└── user.go # 自定义获取函数自定义键定义
package bContext
import xCtx "github.com/bamboo-services/bamboo-base-go/defined/context"
const (
// 用户相关
UserEntityKey xCtx.ContextKey = "business_user_entity"
UserTokenKey xCtx.ContextKey = "business_user_token"
UserPermissionKey xCtx.ContextKey = "business_user_permission"
// 第三方服务
TencentSmsKey xCtx.ContextKey = "business_tencent_sms"
AliyunOssKey xCtx.ContextKey = "business_aliyun_oss"
)节点化注入
package main
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"
bContext "your-project/internal/constant/context"
)
func main() {
reg := xReg.Register(context.Background(), []xRegNode.RegNodeList{
// 框架资源
{Key: xCtx.DatabaseKey, Node: initDatabase},
{Key: xCtx.RedisClientKey, Node: initRedis},
// 业务资源
{Key: bContext.TencentSmsKey, Node: initTencentSms},
{Key: bContext.AliyunOssKey, Node: initAliyunOss},
})
reg.Serve.Run(":8080")
}工具函数
package bCtxUtil
import (
"context"
sms "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms/v20210111"
bContext "your-project/internal/constant/context"
"your-project/internal/entity"
)
func GetUserEntity(ctx context.Context) *entity.User {
if v := ctx.Value(bContext.UserEntityKey); v != nil {
return v.(*entity.User)
}
return nil
}
func MustGetTencentSmsClient(ctx context.Context) *sms.Client {
if v := ctx.Value(bContext.TencentSmsKey); v != nil {
return v.(*sms.Client)
}
panic("腾讯云短信客户端未注入")
}