引言
之前对context的了解比较浅薄,只知道它是用来传递上下文信息的对象;
对于Context本身的存储、类型认识比较少。
最近又正好在业务代码中发现一种用法:在每个协程中都会复制一份新的局部context对象,想探究下这种写法在性能上有没有弊端。
jobList := []func() error{
s.task1,
s.task2,
s.task3,
s.task4,
}
if err := gconc.GConcurrency(jobList); err != nil {
resource.LoggerService.Error(ctx, "exec concurrency job list error", logit.Error("error", err))
}
func (s *Service) task1() (err error) {
if !s.isLogin() {
return nil
}
// 新局部变量,值来自全局的context对象
ctx := s.ctx
return nil
}
基本概念
介绍
golang.org/x/net/context,是golang中的一个标准库,主要作用就是创建一个上下文,实现对程序中创建的协程通过传递上下文信息来实现对协程的管理。

创建一个Context对象
在Go语言中,可以通过多种方式创建Context:
空Context对象
Background()和TODO():这两个函数分别用于创建空的Context,通常作为根节点使用
- Background()通常用于main函数、初始化以及测试;
- TODO()则用于尚未确定使用哪种Context的情况。
可取消的Contex对象
WithCancel(parent Context):创建一个可取消的Context,并返回一个取消函数
- 当调用取消函数时,会通知所有的子Context,使它们都取消执行。
带有截止时间的Context对象
WithDeadline(parent Context, deadline time.Time):创建一个带有截止时间的Context,并返回一个取消函数
- 当超过截止时间时,会自动通知所有的子Context,使它们都取消执行;
- 当超过截止时间时,会自动通知所有的子Context,使它们都取消执行。
带有超时控制的Contex对象
WithTimeout(parent Context, timeout time.Duration):创建一个带有超时控制的Context,它等同于WithDeadline(parent, time.Now().Add(timeout))。
带键值对的Context对象
WithValue(parent Context, key, val interface{}):创建一个带有键值对的Context,同时保留父级Context的所有数据。
- 需要注意Context主要用于传递请求范围的数据,而不是用于存储大量数据或传递业务逻辑中的参数。
分析Context对象
上面介绍了几种创建Context对象的方法,包括创建可取消的Context、带有截止时间的Context以及带有键值对的Context
Context接口
type Context interface {
Deadline()

最低0.47元/天 解锁文章
1553

被折叠的 条评论
为什么被折叠?



