作为一名 Gopher,怎么可以不知道 Go context 呢?快来了解一下吧!
介绍
Go 1.7 标准库引入 context
,中文译作“上下文”,准确说它是 goroutine
的上下文,包含 goroutine
的运行状态、环境、现场等信息。
context
主要用来在 goroutine
之间传递上下文信息,包括:取消信号、超时时间、截止时间、k-v 等。
随着 context
包的引入,标准库中很多接口因此加上了 context
参数,例如 database/sql
包。context
几乎成为了并发控制和超时控制的标准做法。
使用场景
在 Go http
包的 Server
中,每一个请求在都有一个对应的 goroutine
去处理。请求处理函数通常会启动额外的 goroutine
用来访问后端服务,比如数据库和 RPC
服务。用来处理一个请求的 goroutine
通常需要访问一些与请求特定的数据,比如终端用户的身份认证信息、验证相关的 token
、请求的截止时间。当一个请求被取消或超时时,所有用来处理该请求的 goroutine
都应该迅速退出,然后系统才能释放这些 goroutine
占用的资源。
使用规范
- 不要将
Context
放入结构体,相反Context
应该作为第一个参数传入,命名为ctx
,例如:
1 | go复制代码func DoSomething (ctx context.Context,arg Arg) error { |
- 即使函数允许,也不要传入
nil
的Context
。如果不知道用哪种Context
,可以使用context.TODO()
。 - 使用
Context
的Value
相关方法只应该用于在程序和接口中传递的和请求相关的元数据,不要用它来传递一些可选的参数。 - 相同的
Context
可以传递给在不同的goroutine
,因为Context
是并发安全的。
Context 结构体
1 | go复制代码// A Context carries a deadline, cancelation signal, and request-scoped values |
Done()
返回一个channel。当times out或者调用cancel方法时,将会close掉。Err()
返回一个错误。该context为什么被取消掉。Deadline()
返回截止时间和 ok。Value()
返回Key
值。
context 包方法
1 | go复制代码func Background() Context |
Background
和TODO
都是返回空的Context
。WithCancel
以一个新的Done channel
返回一个父Context
的拷贝。WithDeadline
的最后期限调整为不晚于deadline
返回父上下文的副本。WithTimeout
返回WithDeadline(parent, time.Now().Add(timeout))
。WithValue
返回的父与键关联的值在val
的副本。
总结
整个 context
包的源码非常短,很适合学习,一定要去读一下。除了使用 context
控制并发,我们还可以使用 WaitGroup
。
本文转载自: 掘金