Go并发可视化解释 – select语句

上周,我发布了一篇关于如何直观解释Golang中通道(Channel)的文章。如果你对通道仍然感到困惑,请先查看那篇文章。

Go并发可视化解释 — Channel

作为一个快速复习:Partier、Candier和Stringer经营着一家咖啡店。Partier负责接受顾客的订单,然后将这些订单传递给厨房,Candier和Stringer制作咖啡。

Gophers\\’ Cafe(Gopher咖啡馆)

在本文中,我将直观解释select语句,这是在Go应用程序中处理并发的另一个强大工具。Gophers和他们的虚构咖啡馆仍然是我的伙伴,但这次,让我们聚焦在Partier和点单部分。

情景

Gopher的Cafe意识到越来越多的顾客希望通过外卖应用程序在线订购咖啡。因此,除了店内点餐外,他们还选择了一个外卖应用程序。Partier会监视来自两个通道的订单,并通过另一个名为queue的通道将这些订单转发给Candier和Stringer。

select {case order := <-appOrders:    queue <- ordercase order := <-inShopOrders:    queue <- order}

当这两个通道中的任何一个有订单时,Partier会获取订单并将其转发到queue通道。

Go并发可视化解释 – select语句

如果这两个通道都有订单,将会选择其中一个。在实际的咖啡店中,来自inShopOrders的订单可能会被优先处理。但是,在Go应用程序中,我们无法保证哪个订单会被选择。还要注意,select语句的执行只会选择一个订单,Partier不会一次选择两个订单。但是,在许多应用程序中,select语句通常嵌套在for循环中,以便在前一个迭代中剩下的订单有机会在下一个迭代中被选择。

for {    select {    case order := <-appOrders:        queue <- order    case order := <-inShopOrders:        queue <- order    }}

但是,如果这两个通道都有订单,它们将再次进行公平竞争。

默认情况(Default)

在非高峰时段,订单不多,Partier花费大量时间在等待上。他认为,他可以通过做其他事情来更有效地利用时间,例如清理桌子。这可以通过default来实现。

for {    select {    case order := <-appOrders:        log.Println(\\\"There is an order coming from appOrders channel\\\")        queue <- order    case order := <-inShopOrders:        log.Println(\\\"There is an order coming from inShopOrders channel\\\")        queue <- order    default:        log.Println(\\\"There is no order on both channels, I will do cleaning instead\\\")        doCleaning()    }}

time.After()

time.After(duration)通常与select一起使用,以防止永久等待。与default不同,time.After(duration)会创建一个普通的<-chan Time,等待duration时间的流逝,然后将当前时间发送到返回的通道上。这个通道在select语句中与其他通道平等对待。正如你所看到的,select语句中的通道可以是不同类型的。

shouldClose := falsecloseHourCh := time.After(8 * time.Hour)
for !shouldClose { select { case order := <-appOrders: log.Println(\\\"There is an order coming from appOrders channel\\\") queue <- order case order := <-inShopOrders: log.Println(\\\"There is an order coming from inShopOrders channel\\\") queue <- order case now := <-closeHourCh: log.Printf(\\\"It is %v now, the shop is closing\\\\n\\\", now) shouldClose = true default: log.Println(\\\"There is no order on both channels, I will go cleaning instead\\\") doCleaning() }}
log.Println(\\\"Shop is closed, I\\\'m going home now. Bye!\\\")

当处理远程API调用时,这种技术非常常见,因为我们无法保证远程服务器何时返回或是否返回。借助于context,通常不需要这样做。

responseChannel := make(chan interface{})timer := time.NewTimer(timeout)
select {case resp := <-

原创文章,作者:小技术君,如若转载,请注明出处:https://www.sudun.com/ask/34014.html

(0)
小技术君's avatar小技术君
上一篇 2024年4月21日 上午11:38
下一篇 2024年4月21日 上午11:40

相关推荐

  • CDN和高防IP的区别

    CDN和高防IP的区别 在网络安全和性能优化中,CDN(内容分发网络)和高防IP(高防御IP)是两种常见的解决方案,但它们的功能和应用场景有所不同。在本文中,我们将比较CDN和高防…

    2024年3月14日
    0
  • cdn业务,cdn业务给房东出证明

    CDN业务:加速网站,提升用户体验 在当今数字化时代,网站性能和用户体验对于在线业务的成功至关重要。随着互联网流量的不断增长,网站面临着越来越大的性能挑战,例如网站加载速度慢、访问…

    2024年5月11日
    0
  • 探索网络架构的关键角色:六种常用的服务器类型

    在今天的数字时代,服务器是支撑各种在线服务和应用的基石。不同类型的服务器在网络架构中扮演着不同的角色,从网页传输到电子邮件交换,再到文件传输和内容分发。本文将深入探讨六种最常用的服…

    CDN资讯 2024年4月14日
    0
  • 系统设计蓝图 / 备忘单

    开发一个强大、可扩展和高效的系统可能会令人望而却步。然而,了解关键概念和组件可以使这个过程更可管理。在本博客文章中,我们将探讨系统设计的关键概念和组件,如DNS、负载均衡、API网…

    CDN资讯 2024年4月7日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注