Context【Golang】

来自智得网
(重定向自Context(Golang)
跳转至: 导航、​ 搜索

简介

Context示意图

对于分布式系统的交互,除了调用时明确的参数传递之外,传入一些上下文信息是一个良好的工程实践,上下文中可以传入本次调用的一些环境信息,例如发起的IP地址,发起的请求等。

因为分布式系统调用的拓扑关系一般是一个有向无环图,所以上下文也同样存在层级关系或者父子关系,下游的上下文带有上游上下文传入的所有信息,还可以加入自己的信息。

由于存在父子关系,所以上下文除了信息传递之外还可以进行一些控制信息的传递,例如传递超时,取消信息,一旦一个节点的上下文触发了取消,取消信息可以传播给其所有的子孙节点。

Golang的context就是上述上下文的一种实现,Golang的协程之间存在各种较为复杂的关系,比如一个通道的关闭可能会触发多个协程的关闭,还有微服务场景下更为复杂的级联关系,比如http执行过程会可能会启用一个新的协程发起rpc调用,如何优雅的管理这些协程的退出,例如在请求已经超时的情况,把整个调用链的协程全部关闭,Context就可以承担这个功能。

原理

context是golang中定义的一个接口

type Context interface {

    Deadline() (deadline time.Time, ok bool)

    Done() <-chan struct{}

    Err() error

    Value(key interface{}) interface{}
}

context包中提供了context接口的一些实现类,例如emptyCtx,valueCtx,cancelCtx,timerCtx等。

emptyCtx

type emptyCtx int

func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
    return
}

func (*emptyCtx) Done() <-chan struct{} {
    return nil
}

func (*emptyCtx) Err() error {
    return nil
}

func (*emptyCtx) Value(key interface{}) interface{} {
    return nil
}

func (e *emptyCtx) String() string {
    switch e {
    case background:
        return "context.Background"
    case todo:
        return "context.TODO"
    }
    return "unknown empty Context"
}

var (
    background = new(emptyCtx)
    todo       = new(emptyCtx)
)

func Background() Context {
    return background
}

func TODO() Context {
    return todo
}