首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

在 Go 中用 Context 取消操作

首发于:https://studygolang.com/articles/13676

在 Go 中用 Context 取消操作

许多使用 Go 的人都会遇到 context 包。大多数时候 context 用在下游操作, 比如发送 Http 请求、查询数据库、或者开 go-routines 执行异步操作。最普通用法是通过它向下游操作传递数据。很少人知道,但是非常有用的context功能是在执行中取消或者停止操作。

这篇文章会解释我们如何使用 Context 的取消功能,还有通过一些 Context 使用方法和最佳实践让你的应用更加快速和健壮。

我们为什么需要取消操作?

简单来说,我们需要取消来避免系统做无用的操作。想像一下,一般的http应用,用户请求 Http Server, 然后 Http Server查询数据库并返回数据给客户端:

hettp应用

如果每一步都很完美,耗时时图会像下面这样:

耗时图

但是,如果客户端中途中断请求会发生什么?会发生,比如: 请求中途,客户端关闭了浏览器。如果没有取消操作,Application Server 和 数据库 会继续他们的工作,尽管工作的结果会被浪费。

异常耗时图

理想条件下,如果我们知道流程(例子中的 http request)的话, 我们想要下游操作也会停止:

理想耗时图

go context包的取消操作

现在我们知道为什么需要取消操作了,让我们看看在 Golang 里如何实现。因为"取消操作"高度依赖上下文,或者已执行的操作,所以它非常容易通过 context 包来实现。

有两个步骤你需要实现:

监听取消事件

触发取消事件

监听取消事件

包提供了 方法, 它返回一个当 收取到 取消 事件时会接收到一个 类型的 。 监听取消事件只需要简单的等待 就好了例如: 一个 会花2秒去处理事务,如果请求提前取消,我们想立马返回结果:

源代码地址: https://github.com/sohamkamani/blog-example-go-context-cancellation

你可以通过执行这段代码, 用浏览器打开 。如果你在2秒内关闭浏览器,你会看到在控制台打印了 。

触发取消事件

如果你有一个可以取消的操作,你可以通过触发一个 取消事件 。 这个你可以用 包 提供的方法, 它返回一个 t 对象,和一个没有参数的方法。这个方法不会返回任何东西,仅在你想取消这个的时候去调用。

第二种情况是依赖。 依赖的意思是,当一个操作失败,会导致其他操作失败。 例如:我们提前知道了一个操作失败,我们会取消所有依赖操作。

基于时间的取消操作

任何程序对一个请求的最大处理时间都需要维护一个,这可以使用基于时间的取消。这个 基本和上一个例子相同,只是多了一点点:

例如:HTTP API 调用内部的服务。 如果服务长时间没有响应,最好提前返回失败并取消请求。

根据 主页对您的请求的响应速度, 您将收到:

goResponse received, status code: 200

你可以通过设置超时来获得以上2种结果。

陷阱和注意事项

尽管Go的 很好用,但是在使用之前最好记住几点。最重要的就是: 仅可以取消一次。如果想传播多个错误的话, 取消并不是最好的选择,最惯用的场景是你真的想取消一个操作,并通知下游操作发生了一个错误。

另一个要记住的是,一个 实例会贯穿所有你想使用取消操作的方法和 。要避免使用一个已取消的 作为 或者 的参数,这可能导致不确定的事情发生。

via:https://www.sohamkamani.com/blog/golang/2018-06-17-golang-using-context-cancellation/

作者:Soham Kamani 译者:Nelsonken 校对:polaris1119

本文由 GCTT 原创编译,Go 中文网 荣誉推出

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190131B134G400?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券