我是靠谱客的博主 义气板栗,这篇文章主要介绍select case break引发的血案,现在分享给大家,希望可以做个参考。

最近线上一个模块有内存泄漏,加了http pprof后,发现goroutine一直在增长,怀疑是goroutine泄漏导致的内存泄漏。于是死看代码,发现以下代码片段可能存在问题:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
//goroutine ... for{ select { case ... ... case ... ... case <- exitChan: break; } }

代码逻辑中,当socket关闭的时候会往exitChan发送数据,这个时候以上代码中的goroutine就需要跳出for循环,结束该goroutine。
问题就出在break上,这里的break是跳出case,还是跳出for?翻书,select-case没有break,所以我应该是写代码的时候以为这个break会跳出for循环。不能确认,那就写个代码测试一下。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package main import ( "fmt" "time" ) var exitChan chan bool func Waiting1(){ defer func(){ fmt.Println("waiting1 exit") }() //do someting time.Sleep(time.Second *10) exitChan <- true } func Waiting2(){ defer func(){ fmt.Println("waiting2 exit") }() for{ select { case <-time.After(time.Second * 2): fmt.Println("tick event...") case <- exitChan: fmt.Println("exit event...") break } } } func main(){ exitChan = make(chan bool) go Waiting1() go Waiting2() <- time.After(time.Second * 60) fmt.Println("main return") }

运行结果告诉我,select-case下的break果然只是跳出了select的分支,跟C语言中的switch-case一样。只不过C语言中,明确要求要break,而Go则没有要求。
所以,这回stupid了一回,赶紧检查一下其他代码,发现其他select-case的分支,如果要跳出for,都是用的return。可能当时写代码的时候脑袋进了水吧…

最后

以上就是义气板栗最近收集整理的关于select case break引发的血案的全部内容,更多相关select内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(69)

评论列表共有 0 条评论

立即
投稿
返回
顶部