背景
后臺廣告系統(tǒng)匹配由串行轉(zhuǎn)為并行鼠哥,涉及到并發(fā)數(shù)控制和一些資源回收工作熟菲,利用channel去做非常容易實(shí)現(xiàn)。細(xì)節(jié)是魔鬼朴恳,還是寫的少:)
有問題代碼示例
代碼實(shí)現(xiàn)功能很簡單抄罕,for 循環(huán)中接收 N 個(gè) channel 的數(shù)據(jù),業(yè)務(wù) channel 傳送業(yè)務(wù)數(shù)據(jù)于颖,最后一個(gè) ch 用來傳遞取消信號呆贿,如果 ch 接收到數(shù)據(jù)那么退出 for 循環(huán)。按照 C-LIKE 習(xí)慣森渐,理想的輸出肯定這樣的:
start cancel
do something?
do something
do something
receive cancel 0
over
但是真實(shí)情況是:
start cancel
do something
do something
do something
receive cancel :0receive cancel :0 無數(shù)個(gè) receive cancel :0陷入死循環(huán)?
channel 特性
先拋開問題做入,簡單列一個(gè) channel 的特性
1. buffered channel 和 unbuffered channel,緩沖與否的區(qū)別
2. 寫入關(guān)閉的 channel 會(huì)導(dǎo)致panic
3. 數(shù)據(jù)未消費(fèi)完的 buffered channel 關(guān)閉后同衣,是可以讀到未消費(fèi)數(shù)據(jù)
4. 無數(shù)據(jù)的 channel 關(guān)閉后竟块,可以立刻讀到該類型的零值
死循環(huán)原因
上面列的 channel 特性只是為了湊數(shù) ~~
Golang 中的 break 有兩種寫法,一個(gè)是 break耐齐, 一個(gè)是 break [label]浪秘, 見官方文檔蒋情,經(jīng)過測試有如下結(jié)論:
1. 不帶 label 的break,只能退出最近的 loop耸携,并且對 select, switch 無效
2. 帶 label 的 break棵癣,對 for, select , switch 均有效
3. break 的 label 只能附著在同一函數(shù)的 for, select 或 switch 語句上,對比來講 goto 的 label就隨意一些
退出的正確姿勢
或是用 C-Like 的goto