context(上下文)作用
golang中的context主要为了处理单个请求域与多个goroutine之间的数据共享,取消信号,截止时间等问题,在一个网络请求中,创建多个goroutine,就可以通过context去追踪所有的goroutine,
context结构
type Context interface { Deadline() (deadline time.Time, ok bool) Done() <-chan struct{} Err() error Value(key interface{}) interface{} }
-
Deadline方法是获取设置的截止时间的意思,第一个返回式是截止时间,到了这个时间点,Context会自动发起取消请求;第二个返回值ok==false时表示没有设置截止时间,如果需要取消的话,需要调用取消函数进行取消。
-
Done方法返回一个只读的chan,类型为struct{},我们在goroutine中,如果该方法返回的chan可以读取,则意味着parent context已经发起了取消请求,我们通过Done方法收到这个信号后,就应该做清理操作,然后退出goroutine,释放资源。之后,Err 方法会返回一个错误,告知为什么 Context 被取消。
-
Err方法返回取消的错误原因,因为什么Context被取消。
-
Value方法获取该Context上绑定的值,是一个键值对,所以要通过一个Key才可以获取对应的值,这个值一般是线程安全的
context的常用继承方法:
最基本的方法是context.background()
#传递父context作为参数,返回子context和取消函数用来取消context func WithCancel(parent Context) (ctx Context, cancel CancelFunc) #多传截止时间参数,到这个时间会自动取消context,也可以用取消函数提前取消 func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) 同理,过了多少时间自动取消 func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) 生成绑定键值对的context,绑定数据可以通过context.Value访问,可以通过这种方式上下文传递数据 func WithValue(parent Context, key, val interface{}) Context
context的使用与总结:
- 不要把Context放在结构体中,要以参数的方式传递,parent Context一般为Background
- 应该要把Context作为第一个参数传递给入口请求和出口请求链路上的每一个函数,放在第一位,变量名建议都统一,如ctx。
- 给一个函数方法传递Context的时候,不要传递nil,否则在tarce追踪的时候,就会断了连接
- Context的Value相关方法应该传递必须的数据,不要什么数据都使用这个传递
- Context是线程安全的,可以放心的在多个goroutine中传递
- 可以把一个 Context 对象传递给任意个数的 gorotuine,对它执行 取消 操作时,所有 goroutine 都会接收到取消信号。