有时候你可能想分割来自通道的多个值,以便将它们发送到两个独立区域。想象一下:你可能想要在一个通道上接收一系列操作指令,将它们发送给执行者,同时记录操作日志。 与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)就本书提出修改意见。