竹简文档
上下文

自定义注入

扩展上下文,通过节点化系统注入业务自定义数据

自定义注入

除了框架预定义的上下文键,你可以通过节点化系统扩展自定义的业务上下文键。

定义自定义键

在业务项目中创建自定义上下文键常量:

internal/constant/context/business.go
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 时通过自定义节点注入全局资源:

main.go
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
}

方式二:中间件注入

在认证中间件中注入用户实体(请求级资源):

internal/app/middleware/auth_required.go
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()
}

获取自定义数据

创建工具函数

为自定义键创建便捷的获取函数:

pkg/ctx/user.go
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 中使用

internal/handler/user.go
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                 # 自定义获取函数

自定义键定义

internal/constant/context/business.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"
)

节点化注入

main.go
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")
}

工具函数

pkg/ctx/business.go
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("腾讯云短信客户端未注入")
}

下一步

On this page