我正在寻找一种在go中多路复用某些频道输出的解决方案。
我有一个数据源,它是从我发送到单个频道的io.Reader
读取的。另一方面,我有一个从频道读取的websocket请求处理程序。现在碰巧有两个客户端创建了一个websocket连接,它们都是从同一个频道读取的,但每个都只获得了部分消息。
代码示例(简化):
func (b *Bootloader) ReadLog() (<-chan []byte, error) {
if b.logCh != nil {
logrus.Warn("ReadLog called while channel already exists!")
return b.logCh, nil // This is where we get problems
}
b.logCh = make(chan []byte, 0)
go func() {
buf := make([]byte, 1024)
for {
n, err := b.p.Read(buf)
if err == nil {
msg := make([]byte, n)
copy(msg, buf[:n])
b.logCh <- msg
} else {
break
}
}
close(b.logCh)
b.logCh = nil
}()
return b.logCh, nil
}
现在当ReadLog()
被调用两次时,第二次调用只返回第一次调用中创建的通道,这导致上面解释的问题。
问题是:如何进行正确的多路复用?
关心发送或接收网站上的多路复用更好/更容易/更理想吗?
我应该从接收器隐藏频道并使用回调吗?
我此刻有点卡住了。任何提示都是受欢迎的。
答案 0 :(得分:4)
多路复用非常简单:制作一段要复用的通道,启动从原始通道读取的goroutine,并将每条消息复制到切片中的每个通道:
// Really this should be in Bootloader but this is just an example
var consumers []chan []byte
func (b *Bootloader) multiplex() {
// We'll use a sync.once to make sure we don't start a bunch of these.
sync.Once(func(){
go func() {
// Every time a message comes over the channel...
for v := range b.logCh {
// Loop over the consumers...
for _,cons := range consumers {
// Send each one the message
cons <- v
}
}
}()
})
}