Go并发编程-context安全传递数据

Context包-安全传递数据

context包我们就用来做两件事:
控制链路 安全传递数据

安全传递数据,是指在请求执行上下文中线程安全地传递数据,依赖于 WithValue 方法。

因为Go本身没有thread-local机制,所以大部分类似的功能都是借助于 context 来实现的。

例子:
链路追踪的 trace id
AB测试的标记位
压力测试标记位分库
分表中间件中传递 sharding hint
ORM 中间件传递 SQL hint
Web 框架传递上下文

Go并发编程-context安全传递数据_第1张图片

  • 进程内同进程链路传递:context;
  • 微服务跨进程传递:微服务协议特定字段,
    如:Dubbo attachment
    Dubbo的隐式参数attachment了。什么是attachment?可以把它认定为Dubbo协议中的一个扩展点。就有点类似于Http协议,我们可以自定义请求头信息。而在Dubbo中,我们也可以自定义RPC请求中的参数
    如:grpc 在http协议的 header里去传递的。

Context包 父子关系

控制是从上至下的,查找是从下至上的。

context 的实例之间存在父子关系:

  • 当父亲取消或者超时,所有派生的子context 都被取消或者超时当

  • 找 key 的时候,子 context 先看自己有没有,没有则去祖先里面找控制是从上至下的,查找是从下至上的。

ctx := context.Background()
parent := context.WithValue(ctx,mykey{},"my value")

child := context.WitchValue(parent,mykey{},"my new value")

Log("parent mykey:",parent.Value(mykey{}))
Log("child mykey",child.Value(mykey{}))


// child test输出
parent mykey: my value
child mykey: my new value


child2,cancel := context.WitchTimeout(parent,time.Second)
defer cancel()
Log("child2 mykey:",child2.Value(mykey{}))

// child2 test输出
// child2 并没有设置mykey,但会继承自parent的mykey
parent mykey: my value
child mykey: my new value
child2 mykey: my value


 child3 := context.WithValue(parent,newkey{},"child3 value")
 Log("parent newkey", parent.Value(newkey{}))
 Log("child3 newkey", child3.Value(newkey{}))
// child3 test输出
parent newkey:<nil>
child3 newkey: child3 value

总之:儿子新值覆盖了旧值,父亲也拿不到新的值。
儿子新增了key,父亲也拿不到新的key

context包 父无法访问子内容

因为父 context 始终无法拿到子 context 设置的值,所以在逼不得已的时候我们可以在父 context 里面放一个 map,后续都是修改这个 map。


// 逼不得已使用
 parent1 := context.WithValue(ctx,mapData{},map[string]string{})

 child4,cancel := context.WithTimeout(parent1,time.Second)
 defer cancel()
 
 md := child4.Value(mapData{}).(map[string]string{})
 md["key1"] = "value1"
 pmd := parent1.Value(mapData{}).(map[string]string{})
 
 Log("parent1 mapData:", pmd["key1"])

// child4 test输出
parent newkey:<nil>
child3 newkey: child3 value

WithValue 注意会检测 Key type Comparable 可比较的
Go并发编程-context安全传递数据_第2张图片

context包 – valueCtx 实现

valueCtx 用于存储 key-value 数据,特点:

  • 典型的装饰器模式:在已有 Context 的基础上附加一个存储 key-value 的功能
  • 只能存储一个 key, val
    Go并发编程-context安全传递数据_第3张图片
    Go并发编程-context安全传递数据_第4张图片

Go并发编程-context安全传递数据_第5张图片

你可能感兴趣的:(Go,golang)