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:因为这些日志是需要以特定格式输出用于审计的,所以各个中间件自行输出可能会比较难受,主要是想各司其职,不要把心智负担下放到下游中间件)。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.