当前位置:网站首页>golang select机制和超时问题怎么解决
golang select机制和超时问题怎么解决
2022-07-07 06:45:00 【亿速云】
golang select机制和超时问题怎么解决
这篇文章主要介绍了golang select机制和超时问题怎么解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇golang select机制和超时问题怎么解决文章都会有所收获,下面我们一起来看看吧。
golang 中的协程使用非常方便,但是协程什么时候结束是一个控制问题,可以用 select 配合使用。
子协程和父协程的通信通常用 context 或者 chan。我遇到一个通常的使用场景,在子协程中尝试多次处理,父协程等待一段时间超时,我选择用 chan 实现。我以为 select 和 C++ 中 switch 类似,所以最开始代码类似如下:
for { select { case <-ctx.Done(): // process ctx done case <-time.After(time.Second * 3): // process after default: // process code }}
测试发现无法实现 timeout,又仔细查看文档,才发现 golang 中 select 另有玄机。废话少说,直接总结要点:
select 中的 case 必须是进行 chan 的手法操作,也就是只能在 case 中操作 chan,并且是 非阻塞接收 。
select 中的 case 是同时监听的,多个 case 同时操作,并未 switch 中一个个顺序判断。如果多个 case 满足要求,随机执行一个,如果一个没有则阻塞当前的协程(没有 default 情况下)。 很类似 Linux 文件符操作的 select 语义 。
上面说的阻塞是没有 default 的情况下,如果有 default,则执行 default,然后退出 select,也就是不会阻塞当前协程。
回到上述代码,我这个 select 会一直不断的执行 default, time.After
生成的 chan 并不会被阻塞判断,所以根本无法完成我想要的效果。理解了之后重新修改代码:
done := make(char int)go func(c chan int) { for { // process code if { c <- 1 return } } c <- 0}(done)select { case <-ctx.Done(): // process ctx done case <-time.After(time.Second * 3): // process after case <-done: // process code}
开一个新的协程去不断尝试,在外的三个 case 有一个满足,则会执行。但是这里有一个问题非常需要注意: 子协程什么时候退出? 。
因为 gorountine 不能被强制 kill,所以在上述超时的情况下,select 语句执行 case time.After
之后退出, done
这个 chan 已经没有接受方了,因此既没有接受者,又没有缓冲区,结合 chan 的特性,则子协程会一直阻塞无法退出,所以本质上这个实现会导致子协程累积下去,也就是 协程泄露 ,可能会使资源耗尽。
如何避免上述问题呢?一个很简单的想法就是提供缓冲区, done := make(char int, 1)
,这样即使没有接收方,子协程也能完成发送,不会被阻塞。
还要一种办法,上面说了,select 操作 chan,并且可以指定 default,那是不是有思路了呢?
if { select { case done <- 1: default: return }}
关于“golang select机制和超时问题怎么解决”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“golang select机制和超时问题怎么解决”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。
边栏推荐
- Zen - batch import test cases
- C language pointer (Part 2)
- [istio introduction, architecture, components]
- JVM 内存结构 详细学习笔记(一)
- Yapi test plug-in -- cross request
- JVM garbage collection detailed learning notes (II)
- 正则匹配以XXX开头的,XXX结束的
- How long does the PMP usually need to prepare for the exam in advance?
- Postman interface debugging method
- Locust performance test 4 (custom load Policy)
猜你喜欢
STM32 clock system
JMeter JDBC batch references data as input parameters (the simplest method for the whole website)
Regular matching starts with XXX and ends with XXX
【云原生】DevOps(一):DevOps介绍及Code工具使用
Data association between two interfaces of postman
Pytest installation (command line installation)
Expérience de port série - simple réception et réception de données
正则匹配以XXX开头的,XXX结束的
How to use Arthas to view class variable values
Yapi test plug-in -- cross request
随机推荐
Pytest+request+allure+excel interface automatic construction from 0 to 1 [five nails / flying Book notice]
Postman data driven
5A summary: seven stages of PMP learning
Chaosblade: introduction to chaos Engineering (I)
【云原生】DevOps(一):DevOps介绍及Code工具使用
stm32和电机开发(从单机版到网络化)
网易云微信小程序
数据建模中利用3σ剔除异常值进行数据清洗
二叉树高频题型
Windows starts redis service
Postman interface test (II. Set global variables \ sets)
SAP MM STO单据的外向交货单创建后新加ITEM?
[chaosblade: delete pod according to the tag, pod domain name access exception scenario, pod file system i/o failure scenario]
Systick tick timer
C language pointer (special article)
LeetCode每日一题(2316. Count Unreachable Pairs of Nodes in an Undirected Graph)
Information Security Experiment 2: using x-scanner scanning tool
shake数据库中怎么使用Mongo-shake实现MongoDB的双向同步啊?
C language pointer (Part 2)
信息安全实验三 :PGP邮件加密软件的使用