今天就跟大家聊聊有关golang 中 context的作用是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
上下文 context.Context
是Go
语言中用来设置截止日期、同步信号,传递请求相关值的结构体。上下文与 Goroutine
有比较密切的关系,是 Go
语言中独特的设计,在其他编程语言中我们很少见到类似的概念。
context.Context
是 Go
语言在 1.7
版本中引入标准库的接口,该接口定义了四个需要实现的方法,其中包括:
context.Context
被取消的时间,也就是完成工作的截止日期;Channel
,这个
Channel
会在当前工作完成或者上下文被取消后关闭,多次调用
Done
方法会返回同一个
Channel
;context.Context
结束的原因,它只会在
Done
方法对应的
Channe
l 关闭时返回非空的值;如果
context.Context
被取消,会返回
Canceled
错误;如果 c
ontext.Context
超时,会返回
DeadlineExceeded
错误;context.Context
中获取键对应的值,对于同一个上下文来说,多次调用
Value
并传入相同的
Key
会返回相同的结果,该方法可以用来传递请求特定的数据;type Context interface { Deadline() (deadline time.Time, ok bool) Done() <-chan struct{} Err() error Value(key interface{}) interface{}}
context
包中提供的 context.Background
、context.TODO
、context.WithDeadline
和 context.WithValue
函数会返回实现该接口的私有结构体。
func main() { ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() go handle(ctx, 500*time.Millisecond) select { case <-ctx.Done(): fmt.Println("main", ctx.Err()) }}func handle(ctx context.Context, duration time.Duration) { select { case <-ctx.Done(): fmt.Println("handle", ctx.Err()) case <-time.After(duration): fmt.Println("process request with", duration) }}Go
context
包中最常用的方法还是 context.Background
、context.TODO
,这两个方法都会返回预先初始化好的私有变量 background
和 todo
,它们会在同一个 Go
程序中被复用
var ( background = new(emptyCtx) todo = new(emptyCtx))
background 通常用在 main 函数中,作为所有 context 的根节点。
todo 通常用在并不知道传递什么 context 的情形。例如,调用一个需要传递 context 参数的函数,你手头并没有其他 context 可以传递,这时就可以传递 todo。这常常发生在重构进行中,给一些函数添加了一个 Context 参数,但不知道要传什么,就用 todo “占个位子”,最终要换成其他 context。
context.WithCancel
函数能够从context.Context
中衍生出一个新的子上下文并返回用于取消该上下文的函数。一旦我们执行返回的取消函数,当前上下文以及它的子上下文都会被取消,所有的Goroutine
都会同步收到这一取消信号。
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { c := newCancelCtx(parent) propagateCancel(parent, &c) return &c, func() { c.cancel(true, Canceled) }}
func propagateCancel(parent Context, child canceler) { done := parent.Done() if done == nil { return // 父上下文不会触发取消信号 } select { case <-done: child.cancel(false, parent.Err()) // 父上下文已经被取消 return default: } if p, ok := parentCancelCtx(parent); ok { p.mu.Lock() if p.err != nil { child.cancel(false, p.err) } else { p.children[child] = struct{}{} } p.mu.Unlock() } else { go func() { select { case <-parent.Done(): child.cancel(false, parent.Err()) case <-child.Done(): } }() }}
context
包中的 context.WithValue
能从父上下文中创建一个子上下文,传值的子上下文使用 context.valueCtx
类型
func WithValue(parent Context, key, val interface{}) Context { if key == nil { panic("nil key") } if !reflectlite.TypeOf(key).Comparable() { panic("key is not comparable") } return &valueCtx{parent, key, val}}
type valueCtx struct { Context key, val interface{}}func (c *valueCtx) Value(key interface{}) interface{} { if c.key == key { return c.val } return c.Context.Value(key)}
看完上述内容,你们对golang 中 context的作用是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/superhreojim/blog/5018854