break in select will not break t
背景
后台广告系统匹配由串行转为并行,涉及到并发数控制和一些资源回收工作,利用channel去做非常容易实现。细节是魔鬼,还是写的少:)
有问题代码示例
有问题代码代码实现功能很简单,for 循环中接收 N 个 channel 的数据,业务 channel 传送业务数据,最后一个 ch 用来传递取消信号,如果 ch 接收到数据那么退出 for 循环。按照 C-LIKE 习惯,理想的输出肯定这样的:
start cancel
do something
do something
do something
receive cancel 0
over
但是真实情况是:
start cancel
do something
do something
do something
receive cancel :0receive cancel :0 无数个 receive cancel :0陷入死循环
channel 特性
先抛开问题,简单列一个 channel 的特性
1. buffered channel 和 unbuffered channel,缓冲与否的区别
2. 写入关闭的 channel 会导致panic
3. 数据未消费完的 buffered channel 关闭后,是可以读到未消费数据
4. 无数据的 channel 关闭后,可以立刻读到该类型的零值
死循环原因
上面列的 channel 特性只是为了凑数 ~~
Golang 中的 break 有两种写法,一个是 break, 一个是 break [label], 见官方文档,经过测试有如下结论:
1. 不带 label 的break,只能退出最近的 loop,并且对 select, switch 无效
2. 带 label 的 break,对 for, select , switch 均有效
3. break 的 label 只能附着在同一函数的 for, select 或 switch 语句上,对比来讲 goto 的 label就随意一些
退出的正确姿势
break或是用 C-Like 的goto
goto