有時候你可能想分割來自通道的多個值,以便將它們發送到兩個獨立區域。想象一下:你可能想要在一個通道上接收一系列操作指令,將它們發送給執行者,同時記錄操作日志。
與Unix系統的tee命令功能類似,我們用tee-channel來實現同樣的功能。你可以傳遞給它一個用作讀取的通道,它會返回兩個單獨的通道:
```
tee := func(
done <-chan interface{},
in <-chan interface{},
) (_, _ <-chan interface{}) { <-chan interface{}) {
out1 := make(chan interface{})
out2 := make(chan interface{})
go func() {
defer close(out1)
defer close(out2)
for val := range orDone(done, in) {
var out1, out2 = out1, out2 //1
for i := 0; i < 2; i++ { //2
select {
case <-done:
case out1 <- val:
out1 = nil //3
case out2 <- val:
out2 = nil //3
}
}
}
}()
return out1, out2
}
```
***注意:原文例子就是這樣,反復確認沒有貼錯。大家就當偽碼看吧***
1. 我們希望使用使用本地的變量,所以建立了他們的副本。
2. 我們將使用一條select語句,以便寫入out1和out2不會彼此阻塞。 為了確保兩者都順利寫入,我們將執行select語句的兩個迭代。
3. 一旦我們寫入了通道,我們將其副本設置為零,這樣繼續寫入將阻塞,而另一個通道可以繼續執行。
注意寫入out1和out2是緊密耦合的。 直到out1和out2都被寫入,迭代才能繼續。 通常這不是問題,因為無論如何,處理來自每個通道的讀取流程的吞吐量應該是tee之外的關注點,但值得注意。 這是一個快速調用示例:
```
done := make(chan interface{})
defer close(done)
out1, out2 := tee(done, take(done, repeat(done, 1, 2), 4))
for val1 := range out1 {
fmt.Printf("out1: %v, out2: %v\n", val1, <-out2)
}
```
利用這種模式,很容易使用通道作為系統數據的連接點。
* * * * *
學識淺薄,錯誤在所難免。我是長風,歡迎來Golang中國的群(211938256)就本書提出修改意見。
- 前序
- 誰適合讀這本書
- 章節導讀
- 在線資源
- 第一章 并發編程介紹
- 摩爾定律,可伸縮網絡和我們所處的困境
- 為什么并發編程如此困難
- 數據競爭
- 原子性
- 內存訪問同步
- 死鎖,活鎖和鎖的饑餓問題
- 死鎖
- 活鎖
- 饑餓
- 并發安全性
- 優雅的面對復雜性
- 第二章 代碼建模:序列化交互處理
- 并發與并行
- 什么是CSP
- CSP在Go中的衍生物
- Go的并發哲學
- 第三章 Go的并發構建模塊
- Goroutines
- sync包
- WaitGroup
- Mutex和RWMutex
- Cond
- Once
- Pool
- Channels
- select語句
- GOMAXPROCS
- 結論
- 第四章 Go的并發編程范式
- 訪問范圍約束
- fo-select循環
- 防止Goroutine泄漏
- or-channel
- 錯誤處理
- 管道
- 構建管道的最佳實踐
- 便利的生成器
- 扇入扇出
- or-done-channel
- tee-channel
- bridge-channel
- 隊列
- context包
- 小結
- 第五章 可伸縮并發設計
- 錯誤傳遞
- 超時和取消
- 心跳
- 請求并發復制處理
- 速率限制
- Goroutines異常行為修復
- 本章小結
- 第六章 Goroutines和Go運行時
- 任務調度