您的位置 首页 golang

Golang context解读

Context译作 上下文,一般理解为程序单元的一个运行状态、现场、快照,程序单元指的是Goroutine,每个Goroutine在执行之前,都要先知道程序当前的执行状态,通常将这些执行状态封装在一个Context 变量中,传递给要执行的Goroutine中。

context 包实现了在程序单元之间共享状态变量的方法,通过简单的方法,使我们在被调用程序单元的外部,通过设置ctx变量值,将过期或撤销这些信号传递给被调用的程序单元。在网络编程中,若存在A调用B的API, B再调用C的API,若A调用B取消,那也要取消B调用C,通过在A,B,C的API调用之间传递 Context ,以及判断其状态,就能解决此问题,这是为什么gRPC的接口中带上 ctx context.Context 参数的原因之一。

context 包的核心就是 Context 接口:

type Context interface {

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

Done() <-chan struct{}

Err() error

Value(key interface{}) interface{}

}

Deadline是获取设置的截止时间的意思,第一个返回式是截止时间,到了这个时间点,Context会自动发起取消请求;

Done 返回一个只读的chan,类型为 struct {},在goroutine中,如果该方法返回的chan可以读取,则意味着parent context已经发起了取消请求.

Value可以让Goroutine共享一些数据,获得数据是协程安全的,使用这些数据的时候要注意同步.

context使用:

要创建Context树,第一步就是要得到根节点, context.Background 函数的返回值就是根节点:

func Background() Context

该函数返回空的Context,该Context一般由接收请求的第一个Goroutine创建,是与进入请求对应的Context根节点,它不能被取消、没有值、也没有过期时间。它常常作为处理 Request 的顶层context存在。

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)

//WithCancel函数,传递一个父Context作为参数,返回子Context,以及一个取消函数用来取消Context。

func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)

func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)

func WithValue(parent Context, key interface{}, val interface{}) Context

函数都接收一个 Context 类型的参数 parent ,并返回一个 Context 类型的值,这样就层层创建出不同的节点。

范例:

var key string=”name”

func main() {

ctx, cancel := context.WithCancel(context.Background())

//附加值

valueCtx:=context.WithValue(ctx,key,”【监控1】”)

go watch(valueCtx)

time.Sleep(10 * time.Second)

fmt.Println(“可以了,通知监控停止”)

cancel()

//为了检测监控过是否停止,如果没有监控输出,就表示停止了

time.Sleep(5 * time.Second)

}

func watch(ctx context.Context) {

for {

select {

case <-ctx.Done():

//取出值

fmt.Println(ctx.Value(key),”监控退出,停止了…”)

return

default:

//取出值

fmt.Println(ctx.Value(key),”goroutine监控中…”)

time.Sleep(2 * time.Second)

}

}

}

Context使用原则

不要把Context放在结构体中,要以参数的方式传递.

以Context作为参数的函数方法,应该把Context作为第一个参数,放在第一位。

给一个函数方法传递Context的时候,不要传递nil,如果不知道传递什么,就使用context.TODO。

Context的Value相关方法应该传递必须的数据,不要什么数据都使用这个传递。

Context是线程安全的,可以放心的在多个goroutine中传递。

文章来源:智云一二三科技

文章标题:Golang context解读

文章地址:https://www.zhihuclub.com/97199.shtml

关于作者: 智云科技

热门文章

网站地图