golang context包

context package

概述

context包定义了Context接口类型,里面声明了4个方法,分别是:

Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}

对服务器的传入请求应该创建Context,对服务器的传出调用应该接收Context,它们之间的函数调用链必须传递上下文,可以用WithCancelWithDeadlineWithTimeoutWithValue创建的派生上下文代替,当一个上下文被取消时,由它派生的的所有上下文也应该被取消。
WithCancelWithDeadlineWithTimeout函数接受一个Context(父级)并返回一个派生的Context(子级)和一个CancelFunc函数,调用CancelFunc函数会取消子级以及子级的子级上下文,删除父级上下文对子级上下文的引用,并停止任何相关的计数器。调用CancelFunc函数失败会泄露子级及子级的子级上下文,直到父级上下文被取消或者计时器被停止。go vet工具检查CancelFunc函数是否被用于所有控制流路径。

使用Context的程序应该遵循这些规则,以保持跨包的接口一致性,并启用静态分析工具检查context的传播:

  • 不要将Context存储在结构类型中;相反,将Context显式地传递给每个需要它的函数;
  • Context应该是第一个参数,通常命名为ctx,例如
func DoSomething(ctx context.Context, arg Arg) error {
	// ... use ctx ...
}
  • 即使函数允许,也不要传递nil Context,如果不确定传递哪个Context,请传递context.TODO
  • 仅对传输进程和API的请求范围内的数据使用context值, 而不是将可选参数传递给函数
  • 相同的Context可以传递给在不同goroutine中运行的函数;上下文对于多个goroutine同时使用是安全的

CancelFunc类型

CancelFunc 通知操作放弃其工作,CancelFunc不会等待工作停止。多个goroutine可以同时调用CancelFunc,在第一次调用之后,对CancelFunc的后续调用将不执行任何操作。

type CancelFunc func()

Context接口

type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{
Err() error
Value(key interface{}) interface{}
}

Deadline方法

Deadline返回代表此上下文完成的工作应取消的时间。未设置截止日期时,Deadline返回ok==false。连续调用Deadline返回相同的结果。

Done方法

当代表此context完成的工作应取消时,Done返回一个关闭的通道。如果无法取消此context,则Done可能返回nil。连续调用Done返回相同的值。cancel函数返回后,Done通道的关闭可能会异步进行。

  • WithCancel安排在调用cancel时关闭Done
  • WithDeadline安排在期限届满时关闭Done
  • WithTimeout安排在超时结束时关闭Done。
  • Done用于select语句

Err方法

  • 如果Done尚未关闭,Err返回nil
  • 如果关闭Done,Err返回一个非nil错误,解释原因:
    • 如果上下文被取消,则返回Canceled
    • 如果上下文的截止日期已过,则返回DeadlineExceeded。
  • Err返回非nil错误后,对Err的连续调用将返回相同的错误

Value方法

Value返回与上下文关联的key对应的值,如果没有上下文与key关联,则返回nil。使用相同的key连续调用Value将返回相同的结果。

仅对传输进程和API边界的请求范围的数据使用上下文值,而不是将可选参数传递给函数。

key标识上下文中的特定值,希望在上下文中存储值的函数通常在全局变量中分配一个key,然后将该key用作Context.WithValueContext.Value的参数。key可以是任何支持相等的类型。

函数

WithCancel

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

WithCancel 返回具有新Done 通道的父级的副本,当调用返回的cancel函数或父上下文的Done通道关闭时(以先发生的为准),返回的上下文的Done通道会关闭。
取消此上下文将释放与其关联的资源,因此代码应该在该上下文中运行的操作完成后立即调用cancel。

WithDeadline

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

WithDeadline返回父上下文的副本,并将截止日期调整为不晚于d。如果父级上下文的截止日期早于d,则 WithDeadline( parent,d)在语义上等同于parent。当截止日期过期、调用返回的cancel函数或父上下文的Done通道关闭时(以先发生的为准),返回的上下文的Done通道将关闭。
取消此上下文将释放与其关联的资源,因此代码应该在该上下文中运行的操作完成后立即调用cancel。

WithTimeout

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

WithTimeout 返回 WithDeadline(parent, time.Now().Add(timeout))

Background

func Background() Context

Background返回 non-nil 的空上下文,它从不取消,没有值,也没有截止日期,它通常由主函数、初始化和测试使用,并作为传入请求的*上下文。

TODO

func TODO() Context

TODO返回一个non-nil 的空上下文,当不清楚要使用哪个上下文或它还不可用时(因为周围的函数还没有扩展到接受上下文参数),代码应该使用context.TODO。

WithValue

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

WithValue 返回父级的副本,其中与key关联的值是val。
仅对传输进程和API的请求范围内的数据使用上下文值,而不是将可选参数传递给函数。

提供的 key 必须是可比较的,并且不应是string类型或任何其他内置类型,以避免使用context的包之间发生冲突。WithValue的用户应该为键定义自己的类型。为了避免在分配给interface{}时进行分配,上下文 key 通常具有具体的类型struct{}。或者,导出的上下文 key 变量的静态类型应该是指针或接口。

参考文献

Using context cancellation in Go

Go Concurrency Patterns: Context

上下文Context

上一篇:逆向KeInitializeApc KiInsertQueueApc


下一篇:04_SHELL编程之循环语句