Search code examples
goamazon-sqs

Create GO application that Reads from SQS without terminating


I am new to Go and I am not an experienced dev by any means so please feel free to bash away.

I am attempting to create a GO application that will live in a container and read from AWS SQS. The goal would be the app is long living and constantly reads from the Queue.

This is the code I have so far as an example. My biggest question is if this is a bad use of GOTO and is there better way.

Thank you in advance

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/sqs"
)

const (
    maxMessages = 1
)

func GetQueueURL(cfg aws.Config, queue string) (*sqs.GetQueueUrlOutput, error) {
    sqsClient := sqs.NewFromConfig(cfg)

    result, err := sqsClient.GetQueueUrl(context.TODO(), &sqs.GetQueueUrlInput{
        QueueName: &queue,
    })

    if err != nil {
        return nil, err
    }

    return result, nil
}

func GetMessages(cfg aws.Config, queueUrl string, maxMessages int32) (*sqs.ReceiveMessageOutput, error) {
    sqsClient := sqs.NewFromConfig(cfg)

    msgResult, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{
        QueueUrl: &queueUrl,
        MaxNumberOfMessages: maxMessages,
        WaitTimeSeconds: 10,
    })

    if err != nil {
        return nil, err
    }

    return msgResult, nil
}

func main() {

    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        log.Fatal("error")
    }

    queueName := "queue"

    res, err := GetQueueURL(cfg, queueName)
    if err != nil {
        fmt.Printf("Got an error receiving url: %v", err)
    }
    FINDMESSAGE:
        msgRes, err := GetMessages(cfg, *res.QueueUrl, maxMessages)
        if err != nil {
            fmt.Printf("Got an error while trying to retrieve messages: %v", err)
        }

        if len(msgRes.Messages) != 0 {
            fmt.Println("Message Body: " + *msgRes.Messages[0].Body)
            fmt.Println("Message Handle: " + *msgRes.Messages[0].ReceiptHandle)
        }

        fmt.Println("No Messages")

    goto FINDMESSAGE

}

Solution

  • My biggest question is if this is a bad use of GOTO and is there better way.

    any use of goto is a bad use of goto, unless you can express why you use a goto. Your example is a for loop:

    for {
            msgRes, err := GetMessages(cfg, *res.QueueUrl, maxMessages)
            if err != nil {
                fmt.Printf("Got an error while trying to retrieve messages: %v", err)
            }
    
            if len(msgRes.Messages) != 0 {
                fmt.Println("Message Body: " + *msgRes.Messages[0].Body)
                fmt.Println("Message Handle: " + *msgRes.Messages[0].ReceiptHandle)
            }
    
            fmt.Println("No Messages")
    }