前言
创新互联公司坚持“要么做到,要么别承诺”的工作理念,服务领域包括:网站设计制作、成都网站制作、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的德令哈网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!许多使用Go的人,都会用到它的上下文库。大多数使用 context 进行下游操作,比如发出HTTP调用,或者从数据库获取数据,或者在协程中执行异步操作。最常见的用法是传递可由所有下游操作使用的公共数据。然而,一个不太为人所知,但非常有用的上下文特性是,它能够在中途取消或停止一个操作。
本篇文章将解释我们如何利用上下文库的取消特性,并通过一些模式和最佳实践来使用取消,使你的程序更快、更健壮。
为什么需要取消?
简而言之,我们需要取消,以防止我们的系统做不不需要的工作。
考虑HTTP服务器对数据库的调用的常见情况,并将查询的数据返回给客户端:
时间图,如果一切都很完美,就会是这样的:
但是,如果客户端取消了中间的请求,会发生什么呢?例如,如果客户端关闭了他们的浏览器,这可能会发生。如果没有取消,应用服务器和数据库将继续执行它们的工作,即使工作的结果将被浪费:
理想情况下,如果我们知道进程(在本例中是HTTP请求)停止了,我们希望流程的所有下游组件停止工作:
1、上下文取消
现在我们知道了为什么需要取消,让我们来看看如何实现它。因为“取消”的事件与交易或正在执行的操作高度相关,所以它与上下文捆绑在一起是很自然的。
取消的有两个方面,你可能想要实现:
2、监听取消事件
上下文类型提供了 Done() 方法,每当上下文收到取消事件时,它都会返回接收空 struct{} 类型的通道。监听取消事件就像等待 <-ctx.done() 一样简单。
例如,让我们考虑一个HTTP服务器,它需要两秒钟来处理一个事件。如果在此之前请求被取消,我们希望立即返回:
func main() { // Create an HTTP server that listens on port 8000 http.ListenAndServe(":8000", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() // This prints to STDOUT to show that processing has started fmt.Fprint(os.Stdout, "processing request\n") // We use `select` to execute a peice of code depending on which // channel receives a message first select { case <-time.After(2 * time.Second): // If we receive a message after 2 seconds // that means the request has been processed // We then write this as the response w.Write([]byte("request processed")) case <-ctx.Done(): // If the request gets cancelled, log it // to STDERR fmt.Fprint(os.Stderr, "request cancelled\n") } })) }
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。