Golang Context使用

Golang Context使用教程

context 在 Go1.7 之后就进入标准库中了。它主要的用处如果用一句话来说,是在于控制 goroutine 的生命周期。当一个计算任务被 goroutine 承接了之后,由于某种原因(超时,或者强制退出)我们希望中止这个 goroutine 的计算任务,那么就用得到这个 Context 了。

Context 有四种结构,即 CancelContext、TimeoutContext、DeadLineContext 和 ValueContext。

Golang Context应用场景

在 Go http 包的 Server 中,每一个请求在都有一个对应的 goroutine 去处理。请求处理函数通常会启动额外的 goroutine 用来访问后端服务,比如数据库和 RPC 服务。

用来处理一个请求的 goroutine 通常需要访问一些与请求特定的数据,比如终端用户的身份认证信息、验证相关的 token、请求的截止时间。当一个请求被取消或超时时,所有用来处理该请求的 goroutine 都应该迅速退出,然后系统才能释放这些 goroutine 占用的资源。

go1.6 及之前版本请使用 golang.org/x/net/context。go1.7 及之后已移到标准库 context。

Golang Context原理

Context 的调用应该是链式的,通过 WithCancel,WithDeadline,WithTimeout 或 WithValue 派生出新的 Context。当父 Context 被取消时,其派生的所有 Context 都将取消。

通过 context.WithXXX 都将返回新的 Context 和 CancelFunc。调用 CancelFunc 将取消子代,移除父代对子代的引用,并且停止所有定时器。未能调用 CancelFunc 将泄漏子代,直到父代被取消或定时器触发。go vet 工具检查所有流程控制路径上使用 CancelFuncs。

Golang Context遵循规则

遵循以下规则,以保持包之间的接口一致,并启用静态分析工具以检查上下文传播:

  1. 不要将 Contexts 放入结构体,相反 context 应该作为第一个参数传入,命名为 ctx。 func DoSomething(ctx context.Context,arg Arg)error { // … use ctx … }
  2. 即使函数允许,也不要传入 nil 的 Context。如果不知道用哪种 Context,可以使用 context.TODO()。
  3. 使用 context 的 Value 相关方法只应该用于在程序和接口中传递的和请求相关的元数据,不要用它来传递一些可选的参数。
  4. 相同的 Context 可以传递给在不同的 goroutine;Context 是并发安全的。

Golang Context详解

使用

context 是 Go 中广泛使用的程序包,由 Google 官方开发,在 1.7 版本引入。它用来简化在多个 go routine 传递上下文数据、(手动/超时)中止 routine 树等操作,比如,官方 http 包使用 context 传递请求的上下文数据,gRpc 使用 context 来终止某个请求产生的 routine 树。由于它使用简单,现在基本成了编写 go 基础库的通用规范。

语法

// A Context carries a deadline, cancelation signal, and request-scoped values // across API boundaries. Its methods are safe for simultaneous use by multiple // goroutines. type Context interface { // Done returns a channel that is closed when this Context is canceled // or times out. Done() <-chan struct{} // Err indicates why this context was canceled, after the Done channel // is closed. Err() error // Deadline returns the time when this Context will be canceled, if any. Deadline() (deadline time.Time, ok bool) // Value returns the value associated with key or nil if none. Value(key interface{}) interface{} }

说明

函数 说明
Done() 返回一个 channel。当 times out 或者调用 cancel 方法时,将会 close 掉。
Err() 返回一个错误。该 context 为什么被取消掉。
Deadline() 返回截止时间和 ok。
Value() 返回值。

Golang Context所有方法

方法

func Background() Context func TODO() Context 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, val interface{}) Context

说明

上面可以看到 Context 是一个接口,想要使用就得实现其方法。在 context 包内部已经为我们实现好了两个空的 Context,可以通过调用 Background() 和 TODO() 方法获取。一般的将它们作为 Context 的根,往下派生。

Golang Context使用总结

context 在 Go1.7 之后就进入标准库中了。它主要的用处如果用一句话来说,是在于控制 goroutine 的生命周期。当一个计算任务被 goroutine 承接了之后,由于某种原因(超时,或者强制退出)我们希望中止这个 goroutine 的计算任务,那么就用得到这个 Context 了。

Context 有四种结构,即 CancelContext、TimeoutContext、DeadLineContext 和 ValueContext。