Design patterns for map channel?

huangapple go评论89阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2014年1月23日 14:30:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/21300967.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定