You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: consume.go
    path of file: ./repos/microservices/internal/rabbit
    
    the code of the file until where you have to start completion: package rabbit

import (
	"context"
	"fmt"
	"log"

	"github.com/streadway/amqp"
)

// StartConsumer consumes messages from a Rabbit queue with a specified
// routing key and passes them to a supplied handler for processing.
// The queue is created (or connected to, if exists) and bound to an exchange.
// Used for durable queues in the main go routine.
func (conn *Conn) StartConsumer(exch, qName, rKey s
    
func (conn *Conn) StartConsumer(exch, qName, rKey string, handler func(amqp.Delivery) bool) error {
	// Declare a durable queue
	_, err := conn.Channel.QueueDeclare(qName, true, false, false, false, nil)
	if err != nil {
		return fmt.Errorf("queue declare: %v", err)
	}

	err = conn.Channel.QueueBind(qName, "#."+rKey+".#", exch, false, nil)
	if err != nil {
		return fmt.Errorf("queue bind: %v", err)
	}

	// Set prefetchCount above zero to limit unacknowledged messages.
	err = conn.Channel.Qos(0, 0, false)
	if err != nil {
		return err
	}

	// Consume with explicit ack
	msgs, err := conn.Channel.Consume(qName, "", false, false, false, false, nil)
	if err != nil {
		return fmt.Errorf("consume: %v", err)
	}

	go func() {
		for msg := range msgs {
			if handler(msg) {
				msg.Ack(false)
			} else {
				msg.Nack(false, true)
			}
		}
		log.Fatalf("consumer closed")
	}()

	return nil
}