如何(简洁地)删除 Go 中切片中的第一个元素?

我在 Go 中构建了一个简单的队列。它使用一个内部切片来跟踪其元素。元素通过附加到切片被推送到队列中。我想通过删除 elements中的第一个元素来实现 .Pop()

在许多其他语言中,“弹出”列表的第一个元素是一行程序,这使我相信下面的实现是草率和冗长的。还有更好的办法吗?

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
}

请注意,我希望 Queue恐慌,如果 len(queue.elements) == 0。我不检查边界不是疏忽。

69727 次浏览

你试过这些吗?

从队列中跳出来

x, a = a[0], a[1:]

从栈里跳出来

x, a = a[len(a)-1], a[:len(a)-1]

用力

a = append(a, x)

发信人: https://code.google.com/p/go-wiki/wiki/SliceTricks

如果你想要一个环形缓冲区或者 FIFO 结构,那么像@Everton 的答案一样使用一个切片将会导致垃圾收集问题,因为底层数组可能会无限增长。

如果您不介意有一个有限的大小,那么最简单的方法就是使用一个对于并发访问也是安全的通道。这是如此常见的习惯用法,以至于您通常不会费心将它包装成下面这样的类型。

例(游乐场)

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())


}