当前位置:网站首页>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机制和超时问题怎么解决”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。
边栏推荐
- Hard core sharing: a common toolkit for hardware engineers
- Sublime Text4 download the view in bower and set the shortcut key
- C language pointer (special article)
- Expérience de port série - simple réception et réception de données
- Mysql database transaction learning notes
- Using JWT to realize login function
- External interrupt to realize key experiment
- sqlplus乱码问题,求解答
- 数据库多表关联查询问题
- Locust performance test 3 (high concurrency, parameter correlation, assembly point)
猜你喜欢
Mysql数据库-锁-学习笔记
Install pyqt5 and Matplotlib module
Connecting mobile phone with ADB
Serial port experiment - simple data sending and receiving
JVM garbage collection detailed learning notes (II)
嵌套(多级)childrn路由,query参数,命名路由,replace属性,路由的props配置,路由的params参数
Postman interface test (II. Set global variables \ sets)
Nested (multi-level) childrn routes, query parameters, named routes, replace attribute, props configuration of routes, params parameters of routes
Jemter operation
Network request process
随机推荐
Postman interface test (I. installation and use)
NATAPP内网穿透
C language pointer (Part 2)
Detailed learning notes of JVM memory structure (I)
Cesium does not support 4490 problem solution and cesium modified source code packaging scheme
Netease Cloud Wechat applet
Mysql数据库-锁-学习笔记
shake数据库中怎么使用Mongo-shake实现MongoDB的双向同步啊?
LeetCode每日一题(2316. Count Unreachable Pairs of Nodes in an Undirected Graph)
What is MD5
【Istio Network CRD VirtualService、Envoyfilter】
Postman interface test (II. Set global variables \ sets)
Mysql database index study notes
Jenkins automated email
Add new item after the outbound delivery order of SAP mm sto document is created?
PMP certificate preparation experience sharing
Chaosblade: introduction to chaos Engineering (I)
NVIC interrupt priority management
The essence of high availability
What is the use of PMP certificate?