<p>The first question I have is a design question really. This is my first time writing a service that uses a Queue and I am also new to Go. I am trying to determine whether I should write my worker in such a way that it simply pops one message off the queue, processes it, and the dies off. With things like Kubernetes this <em>seems</em> fairly trivial.</p>

<p>Or should I have a long-lived worker constantly waiting for new messages but that is relaunched if it dies (by a bug or accident)?</p>

<p>The reason I ask this question is that in order to implement the former it feels a little more "hacked up" because I have to write the following using the common go AMQP library from <code>streadway/amqp</code> (read the comments):</p>

<pre><code>// Pop will extract a message from the AMQP queue
func (v *Queue) Pop() (data []byte, err error) {
    msgs, err := v.Channel.Consume(
        v.QueueName, // queue
        v.ConsmerID, // consumer
        true,        // auto-ack
        false,       // exclusive
        false,       // no-local
        false,       // no-wait
        nil,         // args
    )
    if err != nil {
        return nil, err
    }

    // We have to use for .. range because Consume returns
    // "&lt;-chan Delivery" but if we only want ONE message popped off
    // we return on the first one
    for data := range msgs {
        return data.Body, nil
    }

    // We should never get this far...
    return nil, errors.New("Something went wrong")
}
</code></pre>

<p>Furthermore what is <code>&lt;-chan Delivery</code> in this case? It seems like some sort of "stream" or object that you can plug into. Is there a way to not have to write a for-loop for these data types?</p>

<p>EDIT: I have also discovered that it appears that this code will dequeue the ENTIRE queue even though it only does a for-loop iteration once (as show in the code above). I am not sure why this happens either?</p>

<p>Relevant links to code:</p>

<ul>
<li><a href="https://github.com/streadway/amqp/blob/master/channel.go#L1049" rel="nofollow noreferrer">https://github.com/streadway/amqp/blob/master/channel.go#L1049</a></li>
<li><a href="https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/go/worker.go" rel="nofollow noreferrer">https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/go/worker.go</a></li>
<li><a href="https://github.com/fatih/amqp-examples/blob/master/consumer.go#L132" rel="nofollow noreferrer">https://github.com/fatih/amqp-examples/blob/master/consumer.go#L132</a></li>
</ul>

<p>To simply take a single object from a <code>&lt;-chan Delivery</code>, don't use a <code>range</code> loop, but the <a href="https://tour.golang.org/concurrency/2" rel="noreferrer">channel operator <code>&lt;-</code></a>:</p>

<pre><code>data := &lt;- msgs
return data.Body, nil
</code></pre>

<p>As to why your entire queue is emptied as soon as you fetch one message: This is most likely due to the <a href="https://www.rabbitmq.com/consumer-prefetch.html" rel="noreferrer">Consumer prefetch</a>. When consuming messages, the client will actually not pop them from the broker one-by-one, but in batches of configurable size (if I recall correctly, around the order of 32 or 64 messages by default). As soon as the broker has published this batch of messages to your consumer, they'll be in your <code>msgs</code> channel; and if you don't read from that channel any more after getting the first message, the rest of them will be gone (at least, with <code>auto-ack</code> enabled -- otherwise, they'll be requeued after the channel is closed).</p>

<p>To only fetch one message at a time, use the channel's <a href="https://godoc.org/github.com/streadway/amqp#Channel.Qos" rel="noreferrer"><code>QoS</code> function</a> (with the first parameter being the prefetch count):</p>

<pre><code>err := v.Channel.Qos(1, 0, false)
</code></pre>
