gopl-zh.github.com/ch8/ch8-04-3.md

55 lines
2.6 KiB
Markdown
Raw Normal View History

2016-01-04 06:26:54 +00:00
### 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`intchannel`<-chan int`intchannel`<-`chanchannel
因爲關閉操作隻用於斷言不再向channel發送新的數據所以隻有在發送者所在的goroutine才會調用close函數因此對一個隻接收的channel調用close將是一個編譯錯誤。
這是改進的版本這一次參數使用了單方向channel類型
2016-01-21 02:39:06 +00:00
<u><i>gopl.io/ch8/pipeline3</i></u>
2016-01-04 06:26:54 +00:00
```Go
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`channelchannelchannel`chan<- int`channel`chan int`channel
2016-01-02 14:05:49 +00:00