Using Azure Storage Queues with Go

This document guides you through interacting with Azure Storage Queues using the Azure SDK for Go.

Azure Queue Storage is a service that stores large numbers of messages that can be processed by a work queue. Each message in Queue Storage is up to 64 KB in size, and a queue can contain any number of messages, up to the limit of the storage account's capacity. Queue Storage is often used to decouple applications, enabling development, deployment, and scaling of different components independently.

Prerequisites

Connecting to a Queue

To interact with a queue, you first need to create a client. You can use a connection string or a credential object.

Using a Connection String


package main

import (
	"context"
	"fmt"
	"log"

	"github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue"
)

func main() {
	// Replace with your actual connection string
	connectionString := "DefaultEndpointsProtocol=https;AccountName=YOUR_ACCOUNT_NAME;AccountKey=YOUR_ACCOUNT_KEY;EndpointSuffix=core.windows.net"
	// Replace with your queue name
	queueName := "my-go-queue"

	// Create a new client
	client, err := azqueue.NewClientFromConnectionString(connectionString, nil)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	// Create the queue if it doesn't exist
	_, err = client.CreateQueue(context.Background(), queueName, nil)
	if err != nil {
		// Ignore error if queue already exists
		// A more robust check might be needed in production
		// fmt.Printf("Warning: Failed to create queue, it might already exist: %v\n", err)
	} else {
		fmt.Printf("Queue '%s' created successfully.\n", queueName)
	}

	fmt.Printf("Successfully connected to queue: %s\n", queueName)

	// You can now use the 'client' to perform queue operations
}
        
Security Note: It is recommended to use Azure Key Vault to store and retrieve your connection strings and account keys securely, rather than hardcoding them directly into your application.

Sending a Message

To send a message to the queue, use the SendMessage method.


func sendMessage(ctx context.Context, client *azqueue.Client, queueName string, messageText string) {
	_, err := client.SendMessage(ctx, queueName, messageText, nil)
	if err != nil {
		log.Fatalf("Failed to send message: %v", err)
	}
	fmt.Printf("Message sent: '%s'\n", messageText)
}

// In your main function:
// sendMessage(context.Background(), client, queueName, "Hello from Go!")
        

Receiving a Message

To receive messages, you can peek at them (without deleting) or dequeue them (which makes them invisible and deletes them after a visibility timeout).

Dequeuing a Message

Dequeuing a message retrieves it and makes it invisible to other consumers for a specified period. After processing, you must delete it.


func receiveAndDeleteMessage(ctx context.Context, client *azqueue.Client, queueName string) {
	// Dequeue a message
	resp, err := client.ReceiveMessage(ctx, queueName, nil)
	if err != nil {
		log.Fatalf("Failed to receive message: %v", err)
	}

	if len(resp.Messages) == 0 {
		fmt.Println("No messages in the queue.")
		return
	}

	message := resp.Messages[0] // Process the first message
	fmt.Printf("Received message (ID: %s): %s\n", *message.ID, *message.MessageText)

	// Delete the message after processing
	_, err = client.DeleteMessage(ctx, queueName, *message.MessageID, *message.PopReceipt, nil)
	if err != nil {
		log.Fatalf("Failed to delete message: %v", err)
	}
	fmt.Printf("Message deleted.\n")
}

// In your main function:
// receiveAndDeleteMessage(context.Background(), client, queueName)
        

Peeking at Messages

Peeking allows you to see messages without making them invisible or deleting them.


func peekMessage(ctx context.Context, client *azqueue.Client, queueName string) {
	resp, err := client.PeekMessages(ctx, queueName, nil)
	if err != nil {
		log.Fatalf("Failed to peek messages: %v", err)
	}

	if len(resp.Messages) == 0 {
		fmt.Println("No messages to peek at.")
		return
	}

	for _, message := range resp.Messages {
		fmt.Printf("Peeked message: %s\n", *message.MessageText)
	}
}

// In your main function:
// peekMessage(context.Background(), client, queueName)
        

Managing Queue Metadata

You can get and set approximate message counts and metadata for a queue.

Getting Queue Properties


func getQueueProperties(ctx context.Context, client *azqueue.Client, queueName string) {
	resp, err := client.GetProperties(ctx, queueName, nil)
	if err != nil {
		log.Fatalf("Failed to get queue properties: %v", err)
	}
	fmt.Printf("Approximate message count for '%s': %d\n", queueName, *resp.ApproximateMessagesCount)
}

// In your main function:
// getQueueProperties(context.Background(), client, queueName)
        

Clearing a Queue

This operation removes all messages from the queue.


func clearQueue(ctx context.Context, client *azqueue.Client, queueName string) {
	err := client.ClearMessages(ctx, queueName, nil)
	if err != nil {
		log.Fatalf("Failed to clear queue messages: %v", err)
	}
	fmt.Printf("All messages cleared from queue '%s'.\n", queueName)
}

// In your main function:
// clearQueue(context.Background(), client, queueName)
        

Deleting a Queue


func deleteQueue(ctx context.Context, client *azqueue.Client, queueName string) {
	_, err := client.Delete(ctx, queueName, nil)
	if err != nil {
		log.Fatalf("Failed to delete queue: %v", err)
	}
	fmt.Printf("Queue '%s' deleted.\n", queueName)
}

// In your main function:
// deleteQueue(context.Background(), client, queueName)
        

Next Steps

Explore more advanced features such as:

For a comprehensive list of all available methods and options, please refer to the official Azure SDK for Go documentation for azqueue.