栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

新提案:增加标准库 Context 的取消 API

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

新提案:增加标准库 Context 的取消 API

大家好,我是煎鱼。

协程(Goroutine)是 Go 语言的一个大杀器,而我们常常需要在多个协程之间进行各种协调和通讯。

图来自 @Soham Kamani

所有 Go 有一个特别独特的东西,他就是上下文(context),你会在各种函数的第一个入参处见到他,标配了。

场景包含但不限于:

  • 依赖 context 传递公共的上下文信息。

  • 使用 goroutine 时进行异步操作,依赖 context 进行取消或返回错误等。

  • 依赖 context 进行跨协程的管理和控制。

背景

标准库 Context 的 API 有许许多多种,今天的主角是 Cancel(取消)行为。

在代码中的 API 调用,如下:

ctx, fn := context.WithCancel(ctx)

结合使用的案例来看,如下:

func operation1(ctx context.Context) error {
 time.Sleep(100 * time.Millisecond)
 return errors.New("failed")
}

func operation2(ctx context.Context) {
 select {
 case <-time.After(500 * time.Millisecond):
  fmt.Println("done")
 case <-ctx.Done():
  fmt.Println("halted operation2")
 }
}

func main() {
 ctx := context.Background()
 ctx, cancel := context.WithCancel(ctx)

 go func() {
  err := operation1(ctx)
  if err != nil {
   cancel()
  }
 }()

 operation2(ctx)
}

在上述程序中,当执行函数 operation1 后,假设返回了错误,就会执行 context.cancel 方法,将正在阻塞执行的 operation2 函数给结束掉。

这么来看,他是一个无比正常普通的 Go 程序。但这里有一个比较折腾的点,那就是你 cancel 取消了上下文后,只知道是被 cancel 了。原因是什么?

为什么被取消,没人知道...?

这就很苦恼了。我朋友在公司里经常看到这种案例,最后大家只能去翻日志或者根据蛛丝马迹去猜逻辑。

是比较不合理的。

新提案

在以前就有人提过类似 issues,就是想 “方便调试上下文被取消的地方”,也就是想解决被取消的场景处理。

经过几年的探讨后,@Sameer Ajmani 提出了新的提案《proposal: context: add APIs for writing and reading cancelation cause》来解决这个问题。

会新增如下几个新的 API:

package context

type CancelCauseFunc func(cause error)

func Cause(c Context) error

func WithDeadlineCause(parent Context, d time.Time, cause error) (Context, CancelFunc)

func WithTimeoutCause(parent Context, timeout time.Duration, cause error) (Context, CancelFunc)

使用案例:

ctx, cancel := context.WithCancelCause(parent)
cancel(myError)

ctx.Err() // returns context.Canceled
context.Cause(ctx) // returns myError

在调用 WithCancelCause 或 WithTimeoutCause 方法后,会返回一个 CancelCauseFunc,而不是 CancelFunc。

其差异之处在于:可以通过传入对应的 Error 等类型的信息,然后在调用Cause 方法来获取其被取消的根因错误。

也就是既能得到被取消时的状态(context.Canceled),也能获取到对应的错误信息(myError),以此来解决前文中所提到的场景。

总结

这篇文章中,我们介绍了 Go 最常见的标准库 Context 的一个设计上的场景缺失。有 Context 状态码是不够的,在业务设计上,状态码和错误信息应该配套。

等该提案合并后,相信以往有过类似经历的同学,可以减少一定的排查时间了...

关注煎鱼,获取业内第一手消息和知识 

你好,我是煎鱼,出版过 Go 畅销书《Go 语言编程之旅》,再到获得 GOP(Go 领域最有观点专家)荣誉,点击蓝字查看我的出书之路。

日常分享高质量文章,输出 Go 面试、工作经验、架构设计,加微信拉读者交流群,和大家交流!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/945577.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号