我在Go中构建了一个简单的队列.它使用内部切片来跟踪其元素.通过附加到切片将元素推送到队列中.我想.Pop()通过删除第一个元素来实现elements.
在许多其他语言中,"弹出"列表的第一个元素是一个单行,这使我相信我的实现在下面是草率和冗长.有没有更好的办法?
type Queue struct {
elements []interface{}
}
func (queue *Queue) Push(element interface{}) {
queue.elements = append(queue.elements, element)
}
func (queue *Queue) Pop() interface{} {
element := queue.elements[0]
if len(queue.elements) > 1 {
queue.elements = queue.elements[1:]
} else {
queue.elements = make([]interface{}, 0)
}
return element
}
Run Code Online (Sandbox Code Playgroud)
请注意,我希望Queue如果恐慌len(queue.elements) == 0.我不检查边界不是疏忽.
Eve*_*ton 52
你试过这些吗?
从队列弹出
x, a = a[0], a[1:]
Run Code Online (Sandbox Code Playgroud)
从堆栈弹出
x, a = a[len(a)-1], a[:len(a)-1]
Run Code Online (Sandbox Code Playgroud)
推
a = append(a, x)
Run Code Online (Sandbox Code Playgroud)
来自:https://code.google.com/p/go-wiki/wiki/SliceTricks
如果您需要环形缓冲区或 FIFO 结构,那么在@Everton 的回答中使用切片会导致垃圾收集问题,因为底层数组可能会无限增长。
如果您不介意限制大小,那么在 go 中执行此操作的最简单方法是使用对于并发访问也是安全的通道。这是 go 中的一个常见习语,您通常不会费心将其包装成如下所示的类型。
例如(游乐场)
package main
import "fmt"
type Queue struct {
elements chan interface{}
}
func NewQueue(size int) *Queue {
return &Queue{
elements: make(chan interface{}, size),
}
}
func (queue *Queue) Push(element interface{}) {
select {
case queue.elements <- element:
default:
panic("Queue full")
}
}
func (queue *Queue) Pop() interface{} {
select {
case e := <-queue.elements:
return e
default:
panic("Queue empty")
}
return nil
}
func main() {
q := NewQueue(128)
q.Push(1)
q.Push(2)
q.Push(3)
fmt.Printf("Pop %d\n", q.Pop())
fmt.Printf("Pop %d\n", q.Pop())
fmt.Printf("Pop %d\n", q.Pop())
fmt.Printf("Pop %d\n", q.Pop())
}
Run Code Online (Sandbox Code Playgroud)