duanchu2607
duanchu2607
2014-05-08 02:48

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

已采纳

I've built a simple queue in Go. It uses an internal slice to keep track of its elements. Elements are pushed onto the queue by appending to the slice. I'd like to implement .Pop() by removing the first element in elements.

In many other languages, "popping" the first element of a list is a one-liner, which leads me to believe my implementation below is sloppy and verbose. Is there a better way?

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
}

Please note that I wish for the Queue to panic if len(queue.elements) == 0. It's not an oversight that I don't check the bounds.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答

  • dtcrw26206 dtcrw26206 7年前

    Did you try these?

    Pop from queue

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

    Pop from stack

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

    Push

    a = append(a, x)
    

    From: https://code.google.com/p/go-wiki/wiki/SliceTricks

    点赞 评论 复制链接分享
  • dspvin19712 dspvin19712 7年前

    If you want a ring buffer or FIFO structure then using a slice as in @Everton's answer will cause garbage collection problems as the underlying array may grow indefinitely.

    The easiest way to do this in go, provided you don't mind having a limited size, is to use a channel which is also safe for concurrent access. This is such a common idiom in go that you wouldn't usually bother wrapping it in a type like the below.

    Eg (Playground)

    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
    ", q.Pop())
        fmt.Printf("Pop %d
    ", q.Pop())
        fmt.Printf("Pop %d
    ", q.Pop())
        fmt.Printf("Pop %d
    ", q.Pop())
    
    }
    
    点赞 评论 复制链接分享

相关推荐