1

我不喜欢 Go 的一件事是通道接收也会从通道中删除数据。这仅允许两个 goroutine 相互通信,即使在某些情况下两个或多个 goroutine 应该能够相互通信。

我知道我可以创建一个通道数组并且每个 goroutine 都有一个通道,但是将数据从一个 goroutine 移动到所有其他 goroutine 比将数据的一个副本移动到所有 goroutine 上的数据要多得多。

考虑一个案例,当我有数千个客户端连接到服务器时,我希望一个只向其中一半的客户端发送消息,即 500 个接收该消息的 goroutine。如果消息是 512 字节,这将在 ram 移动中变成 250 KB 的数据,即使如果通道不会在接收时删除数据,也可以只移动一次相同的数据。

所以我问是否有一些简单的方法可以做到这一点,还是我必须使用同步包中的互斥锁?虽然请告诉我我是否计算错误并且频道不会复制数据,因为在这种情况下我可以管理频道数组。

4

2 回答 2

2

阅读这篇文章:

http://rogpeppe.wordpress.com/2009/12/01/concurrent-idioms-1-broadcasting-values-in-go-with-linked-channels/

这是对跨 goroutine 进行频道广播的不同方式的分析,其中一个特别有趣:

type Broadcaster struct {
    Listenc chan chan (chan broadcast);
    Sendc   chan<- interface{};
}

这种方法被作者称为“链接通道”(类似于链表)。

告诉我是否计算错误并且通道不会复制数据,因为在这种情况下我可以管理通道数组。

你没有错。不过,正如@Jsor 所建议的那样 - 如果您害怕复制开销并且用例允许,您可以传递指针。

于 2013-08-02T08:02:27.033 回答
1

我通常会做这样的事情:

type Message struct {
    text string
    address string
    ...
}

type Server {
    dropbox chan Message
    clients []*Conn
    ...
}

type Conn {
    inbox chan *Message
    ...
}

由读/写 go 例程服务的每个客户端将“消息”放入“保管箱”。服务器从“投递箱”中拉出消息,并根据“地址”确定将消息发送到哪些客户端。

在服务器中,“客户端”甚至可以是一张地图。这实际上取决于您希望如何路由消息:特定的客户端、组等。

你可以用 做一些聪明的事情chan chan T,但是如果你想做智能路由而不是盲目广播,你真的需要一些方法来将消息映射到客户端。

在这种情况下,您不需要 Mutex。在某些情况下,互斥锁是最好的,但在这种情况下,通道要容易得多。

于 2013-08-03T00:09:36.507 回答