作者:kikokikolove | 2023-07-10 14:14
任何人都可以提出转到容器,简单快速的FIF /队列,Go有3个不同的容器:heap
,list
和vector
.哪一个更适合实现队列?
1> Marwan Burel..:
事实上,如果你想要的是一个基本的,易于使用的fifo队列,slice提供了你所需要的一切.
queue := make([]int, 0)
// Push to the queue
queue = append(queue, 1)
// Top (just get next element, don't remove it)
x = queue[0]
// Discard top element
queue = queue[1:]
// Is empty ?
if len(queue) == 0 {
fmt.Println("Queue is empty !")
}
当然,我们假设我们可以信任追加和切片的内部实现,以避免无用的调整大小和重新分配.对于基本用法,这是完全足够的.
此实现的问题在于其内存使用量与出队呼叫数量成正比.
这不是一个好方法,因为每次`queue [1:]`完成时,它会将切片的开始移动到指向下一个元素,但不释放出列元素使用的间隔.实际上,它在切片存储中具有无限的内存增长.此外,如果排队的元素是指针或包含指针的结构,则底层切片存储将保留内存到出队元素,从而导致进一步的内存泄漏.
[SliceTricks:如何使用切片进行矢量化处理](https://code.google.com/p/go-wiki/wiki/SliceTricks).
问题在于该元素会经常被复制.这根本不是问题(复制速度很快),但要记住这一点.
@Florian,此示例代码使用`[] int`进行复制。相反,如果它是`Foo struct {/ *很多字段* /}类型的,则通常使用[[] * Foo`并将队列作为指针,并且根本不会复制元素。(然后,您还想执行“ queue [0] = nil; queue = queue [1:]”以丢弃第一个元素,并从队列中删除对该元素的引用)。
我刚刚在Go 1.11.2中使用了指向结构的指针对其进行了测试。找不到内存泄漏。看起来是一种简单而好的方法。也不需要设置零。https://play.golang.org/p/QAujWCS20xc
@kostya和@tul的评论不正确。只要没有足够的容量容纳新元素,`append`就会创建一个新的后备数组。因此,只要扔掉旧的切片`queue = queue [1:]`,内存使用情况就不会无限。如果切片很大,则可能仍需要一段时间才能收回该内存。
2> saarrrr..:
令人惊讶的是,没有人建议缓冲通道,无论如何,对于大小限制的FIFO队列.
//Or however many you might need + buffer.
c := make(chan int, 300)
//Push
c <- value
//Pop
x <- c
对于不需要持久性的小队列,这应该是默认的事情.即使您正在写入磁盘上的无界队列,从通道写入和读取通常也是一种很好的方法.
是不是x = < - 阻塞呼叫?如果c为空,那么你的go路由可能会挂起,直到队列被补充为止.那不是你想要一个简单的队列数据结构的行为吗?
@ anaken78:select/default子句无法修复,对吧?https://gobyexample.com/non-blocking-channel-operations
3> Evan Shaw..:
矢量或列表应该可以工作,但矢量可能是要走的路.我这样说是因为vector可能比list更少分配和垃圾收集(在当前的Go实现中)相当昂贵.但是,在一个小程序中,它可能无关紧要.
注意:Go 1直接删除容器/矢量包.应更新使用容器/向量的代码以直接使用切片.[Go 1发行说明](http://golang.org/doc/go1):[已删除的软件包](http://golang.org/doc/go1#deleted).[SliceTricks如何使用切片进行矢量化处理](https://code.google.com/p/go-wiki/wiki/SliceTricks).
切片在删除元素时很烂。Slice不能替代可变向量。
4> VonC..:
为了扩展实现方面,Moraes在他的要点中提出了一些来自队列和堆栈的结构:
// Stack is a basic LIFO stack that resizes as needed.
type Stack struct {
nodes []*Node
count int
}
// Queue is a basic FIFO queue based on a circular list that resizes as needed.
type Queue struct {
nodes []*Node
head int
tail int
count int
}
您可以在此操场示例中看到它的运行情况.