作为一名 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
,例如:
func DoSomething (ctx context.Context,arg Arg) error {
// use ctx
}
-
即使函数允许,也不要传入
nil
的Context
。如果不知道用哪种Context
,可以使用context.TODO()
。 -
使用
Context
的Value
相关方法只应该用于在程序和接口中传递的和请求相关的元数据,不要用它来传递一些可选的参数。 -
相同的
Context
可以传递给在不同的goroutine
,因为Context
是并发安全的。
Context 结构体
// 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()
返回Key
值。
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
Background
和TODO
都是返回空的Context
。WithCancel
以一个新的Done channel
返回一个父Context
的拷贝。WithDeadline
的最后期限调整为不晚于deadline
返回父上下文的副本。WithTimeout
返回WithDeadline(parent, time.Now().Add(timeout))
。WithValue
返回的父与键关联的值在val
的副本。
总结
整个 context
包的源码非常短,很适合学习,一定要去读一下。除了使用 context
控制并发,我们还可以使用 WaitGroup
。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18416.html