Go語言的類型系統提供了單方向的channel類型,顧名思義,單向channel只用於發送或者接受數據。channel本身必然是同時支持讀寫否則根本沒法用。假如一個 channel 真的只能讀,那麼肯定只會是空的,因爲你沒機會往裏面寫數據。同理,如果一個 channel 只允許寫,即使寫進去了,也沒有絲毫意義,因爲沒有機會讀取裏面的數據。所謂的單向 channel 概念,其實只是對 channel 的一種使用限制。
- 單向通道的聲明格式
將一個channel變量傳遞到一個函數時,可以通過將其指定爲單向channel變量,從而限制該函數中可以對此channel的操作,比如只能往這個channel寫,或者只能從這個channel讀。
單向channel變量的聲明非常簡單,只能發送的通道類型爲chan<-,只能接收的通道類型爲<-chan,格式如下:
var 通道實例 chan<- 元素類型 // 只能發送通道
var 通道實例 <-chan 元素類型 // 只能接收通道
單向通道的使用例子
例子代碼如下:
- ch := make(chan int)
- // 聲明一個只能發送的通道類型, 並賦值爲ch
- var chSendOnly chan<- int = ch
- //聲明一個只能接收的通道類型, 並賦值爲ch
- var chRecvOnly <-chan int = ch
上面的例子中,chSendOnly 只能發送數據,如果嘗試接收數據,將會出現如下報錯:
invalid operation: <-chSendOnly (receive from send-only type chan<- int)
同理,chRecvOnly也不能發送的
當然,使用make創建通道時,也可以創建一個只發送或讀取的通道:
ch :=make(<-chan int)
var chReadOnly <-chan int = ch
<-chReadOnly
上面代碼編譯正常,運行也是正常。但是,一個不能填充數據(發送)只能讀取的通道是毫無意義的。
- time包中的單向通道
time包中的計時器會返回一個timer實例,代碼如下:
timer:=time.NewTimer(time.Second)
timer的Timer類型定義如下:
type Timer Struct{
c<-chan Time
r runtimeTimer
}
第 2 行中 C 通道的類型就是一種只能接收的單向通道。如果此處不進行通道方向約束,一旦外部向通道發送數據,將會造成其他使用到計時器的地方邏輯產生混亂。因此,單向通道有利於代碼接口的嚴謹性。
- 關閉 channel
關閉channel非常簡單,直接使用Go語言內置的close()函數即可:
close(ch)
在介紹瞭如何關閉channel之後,我們就多了一個問題,如何判斷一個channel是否已經被關閉?我們可以在讀取的時候使用多重返回值的方式:
X.ok:=<-ch
這個用法與 map 中的按鍵獲取 value 的過程比較類似,只需要看第二個 bool 返回值即可,如果返回值是 false 則表示 ch 已經被關閉。