Golang 中的 Context 为什么只有上文没有下文?一般如何传递下文?

24次阅读

共计 1104 个字符,预计需要花费 3 分钟才能阅读完成。

概述

golang 似乎为了保证线程安全,context 不允许修改,只能继承,但这样带来的问题就是上文环境无法获取在下文中更新的 context。

func left(ctx context.Context) {right(ctx)
    value := GetContextValue(ctx, "key")
    fmt.Println(value)
}

func right(ctx context.Context) {ctx := context.WithValue(ctx, "key", "value")
}

因为 right 中 context 并没有改变旧的 ctx,因此 left 中无法获取到 key 的值。

初步想法

我的想法是 ctx 里面塞一个指针,不知道这样是否合理。

// 类似这样,可能不是很准确

func right(ctx context.Context) {sctx := ctx.Value("context").(*SyncContext)
    sctx.Set(...)
}

func left(ctx context.Context) {sctx := ctx.Value("context").(*SyncContext)
    right(ctx)
    fmt.Println(sctx.Get(...))
}

type SyncContext struct {values sync.Map}
func NewSyncContext() *SyncContext { ...}
func (c *SyncContext) Get(key string) any {...}
func (c *SyncContext) Set(key string, value any) {...}

func main() {ctx := context.WithValue(context.Background(), "context", NewSyncContext())
    left(ctx)
}

但感觉这种姿势怪怪的。有没有其他的想法?

场景

大概描述一下我的具体场景,http middleware 使用链式调用,第一个中间件是日志中间件,会在所有 next 调用结束后输出日志,请求、响应这些目前都有办法获取了,就是 next 中间件往 req.Context() 写的数据读不到(因为 req.WithContext 也会创建新的 request,而不是修改 request 的 ctx,目前看到的代码也没有提供修改 request context 的途径)。

主要是 next 中间件会进行一些身份认证,会把用户信息写进 context,需要日志最后打出这些用户信息
(PS:因为这些日志是需要以特定格式输出用于审计的,所以各个中间件自行输出可能会比较难受,主要是想各司其职,不要把心智负担下放到下游中间件)。

正文完
 0