1. 程式人生 > >[Go語言] 操作channel時遇到panic怎麼辦?

[Go語言] 操作channel時遇到panic怎麼辦?

很多同學在使用channel時都遇到過這種情況:Panic問題,相信大家對於這種設計也吐槽了不少吧?這篇文章我們就來扒一扒這樣設計的初衷。

潛在的Panic主要有兩種: 重複close一個channel,向已經closed的channel繼續傳送訊息。

最懶的解決辦法就是通過recover來簡單粗暴的恢復,可是這就違背了設計者的初衷。對於channel c來說,內建的close函式表明了不會再有任何值傳送到c,重複關閉或者向已經關閉的c傳送任何訊息都會導致runtime panic,關閉nil channel也會導致panic。

這裡有個問題,如果c關閉了,繼續從c讀取訊息會怎麼樣?不用擔心,至少不會有panic發生。首先是從c中讀取之前傳送但是還沒有被接收的訊息,當這類訊息接收完了,之後接受到的訊息都是對應channel型別的零值,要注意的是,從一個關閉的channel中接收訊息是完全不會阻塞的!!當然,我們可以通過接收操作的第二個引數來判斷channel是否已經關閉,如果關閉,就不要繼續接收訊息了。

回到上面的recover話題,為什麼不提議這麼做呢,因為一旦這麼做,就意味著你對自己的程式設計時存在什麼潛在的bug根本就不清楚,只想著通過異常處理這種最粗暴的方式來解決。向一個還在開啟的channel傳送訊息,就是設計上可能存在的bug!

其實從底層來說,close也是channel上的一次訊息傳送操作,只不過傳送的是一個特殊的關閉訊息,該訊息就是承諾給系統,該channel絕對不會再收到任何訊息。如果繼續傳送訊息,就會違背這種承諾。同時,由於close也是訊息傳送,因此重複close也會導致panic。

大家應該都知道這個idiom:只應該由傳送方來關閉channel。那同學們肯定也有疑問,那如果同一個channel有多個傳送方呢?這個就是我們程式設計的問題了,如果多個傳送方都要求去關閉channel,但是彼此之間根本就不溝通,那就是有問題的:因為這種情況下,如果某個傳送方要關閉channel,卻不通知其它傳送方,那就存在很大的潛在bug了,至少關閉一個公有頻道,需要得到大家的認可才行!

這裡附上Rob Pike大神的一段原文翻譯:

關閉一個channel就是釋放一個資源。多次關閉一個channel就像多次關閉檔案描述符、多次釋放記憶體塊一樣,都是沒有任何意義的。這些操作都意味著程式碼是有問題的,這也是為什麼我們設計時就強制產生了panic。

看看,大神果然是大神,一句話就闡述清了問題:都是設計和程式碼問題!因此讓自己的設計和程式碼清晰明朗起來是非常重要的,能不用recover解決問題就不用。

總之,Go的設計原則就是簡潔、清晰、不冗餘,用一句流行語來說:我的程式碼,我做主