前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >context.Context是做为参数传递还是存储在struct中?

context.Context是做为参数传递还是存储在struct中?

作者头像
Go学堂
发布2023-01-31 15:13:29
发布2023-01-31 15:13:29
99000
代码可运行
举报
文章被收录于专栏:Go工具箱Go工具箱
运行总次数:0
代码可运行

在很多的API接口中,我们发现函数或方法的第一个参数往往是context.Context。Context在进程通信之间提供了取消、超时以及父子进程之间传递数据的方法。那我们在编码实践中是应该将Context存储于struct中还是以参数的方式在函数或方法直接传递呢?

我们的建议是:context.Context不应该被存储在定义的结构体中,而是应该作为函数的参数进行传递。

首先我们来看看golang语言标准包中针对Context的常用方法:

方法名

作用

withCancel

父进程控制子进程是否取消

withDeadline

父进程控制子进程的结束时间

withTimeout

父进程控制子进程超时时间

withValue

父进程和子进程之间数据传递

通过context包中的几个方法可知,context.Context主要的作用就是用于父子进程之间的控制以及数据传递。因为协程是不可以被进行垃圾回收的,所以Context是在父进程结束后,防止协程泄漏的一种方法。

接下来,我们再来看看如果Context是作为字段属性存储在了struct中,会发生什么。如下例子:

代码语言:javascript
代码运行次数:0
运行
复制
type Worker struct {
  ctx context.Context
}

func New(ctx context.Context) *Worker {
  return &Worker{ctx: ctx}
}

func (w *Worker) Fetch() (*Worker, error) {
  _ = w.ctx 
}

func (w *Worker) Process(w *Worker) error {
  _ = w.ctx 
}

根据以上代码可知,Fetch和Process方法共享同一个ctx,即ctx中设置的超时时间,结束时间,是否结束都将是相同的。这样的缺点就是如果调用者想针对不同的方法设置不同的超时时间、结束时机就变的不可行了

我们再来看看如果Context作为参数传递,而非存储在struct中,又会怎么样呢?如下例子:

代码语言:javascript
代码运行次数:0
运行
复制
type Worker struct {

}

func New() *Worker {
return &Worker{}
}

func (w *Worker) Fetch(ctx context.Context) (*Worker, error) {
  _ = ctx
}

func (w *Worker) Process(ctx context.Context) error {
  _ = ctx
}

当作为函数或方法的参数传递时,ctx的作用域只在该函数或方法内有效,Fetch和Process方法的ctx相互独立。用户可以针对每个方法单独设置超时时间、取消子进程、数据传递等操作而互不影响

总结

context.Context的主要作用就是在父子进程(协程)之间进行超时控制、数据传递。

作为参数传递可以方便使用者针对不同的函数设置不同的超时时间和要传递的参数。

而存储在结构体中,则该结构体的所有方法都会共享该context.Context,适合在定义的struct的生命周期内共享的场景。同时调用者使用时的灵活度会降低。

所以,在使用时的建议是优先作为参数传递

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Go学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档