GoWind 开源生态GoWind 开源生态
首页
框架
GoWind Admin
GoWind CMS
GoWind IM
GoWind UBA
GoWind IoT
GoWind Toolkit
GoWind Quant
GitHub
首页
框架
GoWind Admin
GoWind CMS
GoWind IM
GoWind UBA
GoWind IoT
GoWind Toolkit
GoWind Quant
GitHub
  • 介绍

    • GoWind 框架
    • 框架整体架构
  • go-wind 核心

    • go-wind 核心框架
    • App 生命周期管理
    • Context 传播
    • Transport 抽象
    • Log 门面接口
  • go-wind-plugins 插件

    • go-wind-plugins 插件总览
    • 插件配置系统
    • 插件注册机制(SPI)
    • 日志适配插件
    • 传输协议插件
    • 消息中间件插件
    • 编码解码插件
    • 安全与认证插件
    • 链路追踪插件
    • 缓存插件
    • 对象存储插件(OSS)
    • 限流插件
    • 指标监控插件
    • AI 插件
    • 工作流插件
    • 数据库与缓存插件
    • Bootstrap 集成与网关插件
    • 压缩与序列化插件
    • 模板渲染与验证插件
  • go-wind-bootstrap 启动器

    • go-wind-bootstrap 声明式启动器
    • Bootstrap 配置系统
    • Bootstrap SPI 机制
    • 声明式中间件编排
    • Bootstrap CLI 工具
    • Bootstrap 实战示例
  • 教程

    • 快速入门教程
    • 自定义插件开发教程
    • 多协议同时监听教程
    • 框架迁移指南

Context 传播

go-wind 的 Context 模块提供请求级元数据传播,包括 TraceID、UserID、ColorTag(灰度标识)等,通过深拷贝防止数据竞争。

一、Context 设计

// context.go
type contextKey string

const (
    TraceIDKey contextKey = "trace_id"
    UserIDKey  contextKey = "user_id"
    MetadataKey contextKey = "metadata"
)

// 设置和获取 TraceID
func WithTraceID(ctx context.Context, traceID string) context.Context {
    return context.WithValue(ctx, TraceIDKey, traceID)
}

func TraceID(ctx context.Context) string {
    if v, ok := ctx.Value(TraceIDKey).(string); ok {
        return v
    }
    return ""
}

二、传播的元数据

Key类型说明
trace_idstring链路追踪 ID,贯穿整个请求链路
user_idstring当前用户 ID
metadatamap[string]string自定义元数据
color_tagstring灰度/染色标识,用于流量路由

三、使用方式

3.1 设置和获取

// 在请求入口设置
ctx := wind.WithTraceID(ctx, generateTraceID())
ctx = wind.WithUserID(ctx, "user_123")

// 在业务逻辑中获取
traceID := wind.TraceID(ctx)   // "abc-123"
userID := wind.UserID(ctx)     // "user_123"

3.2 中间件注入

func TraceMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 从请求头提取或生成 TraceID
        traceID := r.Header.Get("X-Trace-ID")
        if traceID == "" {
            traceID = uuid.New().String()
        }

        // 注入到 Context
        ctx := wind.WithTraceID(r.Context(), traceID)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

3.3 跨服务传播

// gRPC 客户端:将 TraceID 注入 metadata
func injectTraceID(ctx context.Context) context.Context {
    traceID := wind.TraceID(ctx)
    return metadata.AppendToOutgoingContext(ctx, "x-trace-id", traceID)
}

// gRPC 服务端:从 metadata 提取 TraceID
func extractTraceID(ctx context.Context) context.Context {
    md, _ := metadata.FromIncomingContext(ctx)
    if vals := md.Get("x-trace-id"); len(vals) > 0 {
        return wind.WithTraceID(ctx, vals[0])
    }
    return ctx
}

四、深拷贝与并发安全

// Context 的 metadata 使用深拷贝,防止并发修改
func WithMetadata(ctx context.Context, key, value string) context.Context {
    existing := getMetadata(ctx)
    // 深拷贝
    copied := make(map[string]string, len(existing)+1)
    for k, v := range existing {
        copied[k] = v
    }
    copied[key] = value
    return context.WithValue(ctx, MetadataKey, copied)
}

相关文档

  • 核心框架介绍
  • App 生命周期管理
  • Transport 抽象
  • 链路追踪插件
Edit this page
Last Updated:: 6/21/26, 9:28 PM
Contributors: Bobo
Prev
App 生命周期管理
Next
Transport 抽象