英文:
Design patterns for map channel?
问题
我正在使用golang编写一个DNS协议解析器,想法是使用以下类似的映射:
var tidMap map[uint16]chan []byte
对于tidMap
映射,键是tid(事务ID),值是一个字节数组通道。
这个想法是一个goroutine将尝试从通道中获取值,另一个goroutine将通过监听每个传入的数据包来尝试读取字节,并一旦找到事务ID,就会将响应数据设置到tidMap
中,以便前一个goroutine可以继续处理响应。
设计中的一个问题是,我需要确保通道的缓冲区长度为1,这样可以将额外的值推送到通道中而不会阻塞。
那么,我如何在tidMap
声明中指定通道的缓冲区长度?
var tidMap map[uint16]chan []byte = make(map[uint16]chan []byte)
你不能在那里使用make()
函数。
英文:
I am writing a DNS protocol parser in golang, the idea is to use a map like this
var tidMap map[uint16] (chan []byte)
So for the tidMap
map, key is the tid (transaction ID), value is a byte array channel.
The idea is that a goroutine will try get value from the channel, another goroutine will try read bytes by listening every imcoming packet, and once found transaction ID, will set response data to the tidMap, so the former goroutine will continue handle the response.
One problem with the design is that I need the make sure the channel has buffer length of 1, so extra values can be pushed into channel without blocking.
So how can I specify channel buffer length in tidMap
declaration?
var tidMap map[int] make(chan int, 1)
You can't use make()
there.
答案1
得分: 1
通道缓冲区的长度并不传达“类型”,因此您需要添加逻辑来测试映射条目是否存在,如果不存在:
tidMap[0] = make(chan int, 1)
英文:
The length of the channel buffer doesn't convey type, so you will have to add logic to test if the map entry exists, if it doesn't:
tidMap[0] = make(chan int, 1)
答案2
得分: 0
简短回答:你无法定义通道的容量作为映射的一部分。当你创建一个映射时,你只定义了键和值的数据类型。
更详细的回答是:创建一个抽象数据类型来隐藏这个实现细节。可以像这样定义一个类型:
type ChannelMap struct {
tidMap map[int](chan []byte)
}
func NewChannelMap() *ChannelMap { ... }
func (c *ChannelMap) Put(tid int) (chan int) {
res := make(chan int, 1)
c.tidMap[tid] = res
return res
}
func (c *ChannelMap) Get(tid int) (chan int) {
return c.tidMap[tid]
}
需要注意的是,给通道设置容量为1并不能确保发送者永远不会阻塞;如果通道的消费者太慢,生产者可以将通道填满到其容量,然后阻塞直到通道再次有空间。
英文:
The short answer: you can't. When you make
a map, you define the data types of its keys and values, and the capacity of a channel is not part of its type.
The longer answer is: create an abstract data type that hides this implementation detail. Something like this:
type ChannelMap struct {
tidMap map[int](chan []byte)
}
func NewChannelMap() *ChannelMap { ... }
func (c *ChannelMap) Put(tid int) (chan int) {
res := make(chan int, 1)
c.tidMap[tid] = res
return res
}
func (c *ChannelMap) Get(tid int) (chan int) {
return c.tidMap[tid]
}
And just to be sure: giving the channel a capacity of 1 does not ensure that senders will never block; if your channel consumers are too slow, producers can fill the channel up to its capacity and will then block until the channel has room again.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论