From b1f7e35f7d1f726e0db8376b9f855cbfa5e2761c Mon Sep 17 00:00:00 2001 From: chai2010 Date: Mon, 4 Jan 2016 14:26:54 +0800 Subject: [PATCH] ch8-04-3 done --- ch8/ch8-04-3.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/ch8/ch8-04-3.md b/ch8/ch8-04-3.md index 48f2ad1..f2abc74 100644 --- a/ch8/ch8-04-3.md +++ b/ch8/ch8-04-3.md @@ -1,3 +1,54 @@ -### 8.4.3. 單向的Channels +### 8.4.3. 單方向的Channel + +隨着程序的增長,人們習慣於將大的函數拆分爲小的函數。我們前面的例子中使用了三個goroutine,然後用兩個channels連鏈接它們,它們都是main函數的局部變量。將三個goroutine拆分爲以下三個函數是自然的想法: + +```Go +func counter(out chan int) +func squarer(out, in chan int) +func printer(in chan int) +``` + +其中squarer計算平方的函數在兩個串聯Channels的中間,因此擁有兩個channels類型的參數,一個用於輸入一個用於輸出。每個channels都用有相同的類型,但是它們的使用方式想反:一個隻用於接收,另一個隻用於發送。參數的名字in和out已經明確表示了這個意圖,但是併無法保證squarer函數向一個in參數對應的channels發送數據或者從一個out參數對應的channels接收數據。 + +這種場景是典型的。當一個channel作爲一個函數參數是,它一般總是被專門用於隻發送或者隻接收。 + +爲了表明這種意圖併防止被濫用,Go語言的類型繫統提供了單方向的channel類型,分别用於隻發送或隻接收的channel。類型`chan<- int`表示一個隻發送int的channel,隻能發送不能接收。相反,類型`<-chan int`表示一個隻接收int的channel,隻能接收不能發送。(箭頭`<-`和關鍵字chan的相對位置表明了channel的方向。)這種限製將在編譯期檢測。 + +因爲關閉操作隻用於斷言不再向channel發送新的數據,所以隻有在發送者所在的goroutine才會調用close函數,因此對一個隻接收的channel調用close將是一個編譯錯誤。 + +這是改進的版本,這一次參數使用了單方向channel類型: + +```Go +gopl.io/ch8/pipeline3 +func counter(out chan<- int) { + for x := 0; x < 100; x++ { + out <- x + } + close(out) +} + +func squarer(out chan<- int, in <-chan int) { + for v := range in { + out <- v * v + } + close(out) +} + +func printer(in <-chan int) { + for v := range in { + fmt.Println(v) + } +} + +func main() { + naturals := make(chan int) + squares := make(chan int) + go counter(naturals) + go squarer(squares, naturals) + printer(squares) +} +``` + +調用counter(naturals)將導致將`chan int`類型的naturals隱式地轉換爲`chan<- int`類型隻發送型的channel。調用printer(squares)也會導致相似的隱式轉換,這一次是轉換爲`<-chan int`類型隻接收型的channel。任何雙向channel向單向channel變量的賦值操作都將導致該隱式轉換。這里併沒有反向轉換的語法:也就是不能一個將類似`chan<- int`類型的單向型的channel轉換爲`chan int`類型的雙向型的channel。 + -TODO