golang 之 context包
Posted flash55
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 之 context包相关的知识,希望对你有一定的参考价值。
概述
context
是Go中广泛使用的程序包,由Google官方开发,在1.7版本引入。它用来简化在多个go routine传递上下文数据、(手动/超时)中止routine树等操作,比如,官方http包使用context传递请求的上下文数据,gRpc使用context来终止某个请求产生的routine树。每个Context应该视为只读的,通过WithCancel、WithDeadline、WithTimeout和WithValue函数可以基于现有的一个Context(称为父Context)派生出一个新的Context(称为子Context)。其中WithCancel、WithDeadline和WithTimeout函数除了返回一个派生的Context以外,还会返回一个与之关联CancelFunc类型的函数,用于关闭Context。通过调用CancelFunc来关闭关联的Context时,基于该Context所派生的Context也都会被关闭,并且会将自己从父Context中移除,停止和它相关的timer。
核心接口
type Context interface Deadline() (deadline time.Time, ok bool) Done() <-chan struct Err() error Value(key interface) interface
根据如上接口显示对每个方法介绍
Done
会返回一个channel,当该context被取消的时候,该channel会被关闭,同时对应的使用该context的routine也应该结束并返回。Context
中的方法是协程安全的,这也就代表了在父routine中创建的context,可以传递给任意数量的routine并让他们同时访问。Deadline
会返回一个超时时间,routine获得了超时时间后,可以对某些io操作设定超时时间。Value
可以让routine共享一些数据,当然获得数据是协程安全的。
在请求处理的过程中,会调用各层的函数,每层的函数会创建自己的routine,是一个routine树。所以,context也应该反映并实现成一棵树。
创建context
在创建context时会通过context.Background
函数的返回值是一个空的context,作为树的根结点。并且提供4个常用函数去创建其子节点。
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) 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
需要注意的是每个函数都会返回一个CancelFunc。调用CancelFunc对象将撤销对应的Context对象,这样父结点的所在的环境中,获得了撤销子节点context的权利,当触发某些条件时,可以调用CancelFunc对象来终止子结点树的所有routine。
我们在子集中可以通过 cxt.Done(
)是否为空来判断。
select case <-cxt.Done(): // do some cleaning and return
WithDeadline
和WithTimeout
比WithCancel
多了一个时间参数,它指示context存活的最长时间。如果超过了过期时间,会自动撤销它的子context。所以context的生命期是由父context的routine和deadline
共同决定的。
WithValue
返回parent的一个副本,该副本保存了传入的key/value,而调用Context接口的Value(key)方法就可以得到val。注意在同一个context中设置key/value,若key相同,值会被覆盖。
示例
package main import ( "fmt" "time" "golang.org/x/net/context" ) func main() ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*5) ctx = context.WithValue(ctx, "Test", "123456") defer cancelFunc() if t, ok := ctx.Deadline(); ok fmt.Println(time.Now()) fmt.Println(t.String()) go func(ctx context.Context) fmt.Println(ctx.Value("Test")) for select case <-ctx.Done(): fmt.Println(ctx.Err()) return default: continue (ctx) time.Sleep(time.Second * 3)
以上是关于golang 之 context包的主要内容,如果未能解决你的问题,请参考以下文章