Return values AWS SDK

As an example for multi-value return, we use the AWS SDK. This small program creates a SNS Topic.

To see all SNS Topics before and after, use this AWS CLI command:

aws sns list-topics --query "Topics[*].TopicArn"
  1 package main
  2
  3 import (
  4         "context"
  5         "fmt"
  6
  7         "github.com/aws/aws-sdk-go-v2/aws"
  8         "github.com/aws/aws-sdk-go-v2/config"
  9         "github.com/aws/aws-sdk-go-v2/service/sns"
 10 )
 11
 12 func main() {
 13         topic := aws.String("go-topic")
 14
 15         cfg, err := config.LoadDefaultConfig(context.TODO())
 16         if err != nil {
 17                 panic("configuration error, " + err.Error())
 18         }
 19
 20         client := sns.NewFromConfig(cfg)
 21
 22         parms := &sns.CreateTopicInput{
 23                 Name: topic,
 24         }
 25
 26         results, err := client.CreateTopic(context.TODO(), parms)
 27         if err != nil {
 28                 panic("sns error, " + err.Error())
 29         }
 30
 31         fmt.Println(*results.TopicArn)
 32 }
package main

import (
        "context"
        "fmt"

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

func main() {
        topic := aws.String("go-topic")

        cfg, err := config.LoadDefaultConfig(context.TODO())
        if err != nil {
                panic("configuration error, " + err.Error())
        }

        client := sns.NewFromConfig(cfg)

        parms := &sns.CreateTopicInput{
                Name: topic,
        }

        results, err := client.CreateTopic(context.TODO(), parms)
        if err != nil {
                panic("sns error, " + err.Error())
        }

        fmt.Println(*results.TopicArn)
}

How it works

In line 26 the two return values are copied into the variables results and err. To know how the return values are defined we look at the AWS GO SDK documentation.

With VSCode (and the go plugin), we get the link to the documentation with a mouse over in line 26:

SNS GO SDK docu

The documentation says:

func (c *Client) CreateTopic(ctx context.Context, params *CreateTopicInput, optFns ...func(*Options)) (*CreateTopicOutput, error)

So we have these two values:

Pointer to CreateTopicOutput

This is the CreateTopicOutput structure:

type CreateTopicOutput struct {

	// The Amazon Resource Name (ARN) assigned to the created topic.
	TopicArn *string

	// Metadata pertaining to the operation's result.
	ResultMetadata middleware.Metadata
	// contains filtered or unexported fields
}

We get back the TopicArn and some metadata. The TopicArn is the unique id which we can use to manage the topic, like deleting it (see cleanup).

In this example we give the topicname as a fixed string, so we know in advance which value the TopicArn will have. But if we generate a dynamic name, we need the information.

So we can print the TopicArn, because it is a variable inside the result structure pointer:

 31         fmt.Println(*results.TopicArn)

Error

The general error handling is that the error variable contains nil if everything is ok.

So this is the error handling:

 27         if err != nil {
 28                 panic("sns error, " + err.Error())
 29         }

Usually you don’t use panic, because this ends the program, but you use the error code to the calling function with or without logging some error infos.

if err != nil {
    // log something
    return err
}     

If you have the “two return variable” setup, you return the error code and an empty pointer to the struct:

if err != nil {
    // log something
    return nil,err
}     

At the end of your function, you would return nil as error:

    // successfull end of function
    return &myStructureVar, nil
}     

If you do not use an assigned variable, go will give a warning and will not run. To avoid that you may use ‘_’ as an “forget the value” variable.

Don’t use error return value:

 results, _ := client.CreateTopic(context.TODO(), parms)

Execute program

Copy the program code without line numbers into a file named main.go, then execute the program:

go run main.go

That gives the topic ARN

arn:aws:sns:eu-central-1:555553403305:go-topic

Where 555553403305 is the account number

Cleanup

You can use this arn to delete the topic:

aws sns delete-topic --topic-arn arn:aws:sns:eu-central-1:555553403305:go-topic

Conclusion

Returning a structure and an error has several pros:

  • If more information is added, you change the struct definition. You don’t have to add return values
  • In AWS SDK its the same pattern for almost all functions, yo you have the principle of least surprise

See also