AWS Developer Tools Blog

Getting started with the AWS Cloud Development Kit and Go

We are excited to announce that Go support for AWS CDK is now in Developer Preview. This means it is now ready for you to test drive in your own CDK applications. This post will show you how to initialize a new AWS CDK app as well as the basics of creating and deploying AWS CDK stacks using the Go programming language.

For more information about continuing development as it approaches stability, check out the project board in the jsii github repository. Additionally, we would love to hear about your experience. We encourage you to open a github issue for any bugs you may encounter as well as features that you would like to see added.

Creating a Go CDK Application

First, make sure you have the latest version of the AWS CDK CLI installed via npm.

$ npm install -g aws-cdk

Additionally, make sure to install the Go compiler toolchain version 1.16 or newer. You can find download and installation instructions for your platform at https://golang.org/dl/.

Next, create a new AWS CDK application in Go using cdk init

$ mkdir hello-cdk-go
$ cd hello-cdk-go
$ cdk init --language=go

This will create the initial files needed for an AWS CDK Go application in the current directory. It will also output a description of the commands needed to synthesize and deploy your stacks.

# Welcome to your CDK Go project!

This is a blank project for Go development with CDK.

**NOTICE**: Go support is still in Developer Preview. This implies that APIs may change while we address early 
feedback from the community. We would love to hear about your experience through GitHub issues.

## Useful commands

 * `cdk deploy`      deploy this stack to your default AWS account/region
 * `cdk diff`        compare deployed stack with current state
 * `cdk synth`       emits the synthesized CloudFormation template
 * `go test`         run unit tests

Now, with your basic application scaffolded, examine the source files that were created by cdk init

├── README.md
├── hello-cdk-go.go
├── hello-cdk-go_test.go
├── cdk.json
└── go.mod
  • README.md – The top level readme for your cdk project
  • hello-cdk-go.go – Your Go program’s main entrypoint
  • hello-cdk-go_test.go – Your unit tests for your application
  • cdk.json – A configuration file that tells the cdk cli how to build and run your application
  • go.mod – The go module definition for your cdk app. This is where dependencies are declared on the aws-cdk Go packages that you need.

With the Go toolchain and CDK CLI installed you now have a working CDK Go Application!

Synthesizing Your Stack

Synthesizing your stack will generate a local directory, cdk.out, which contains your application’s build artifact. This artifact is known as a cloud assembly and it contains an AWS CloudFormation template along with any assets and other resources required to deploy your application to AWS. The generated template’s structure is output to the console.

$ cdk synth
Resources:
  MyTopic86869434:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: MyCoolTopic
    Metadata:
      aws:cdk:path: HelloCdkGoStack/MyTopic/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Analytics: v2:deflate64:H4sIAAAAAAAAAyWJQQrCMBAA39J73BLQQs/9QfUuYRNlW7Mr2Q0tlP5dq6cZZjz0F/BNFhaMM2xXCzi7sOhdWWG7yZvQDQ/+ye4GYbVS0Y42JpVaMB3+HZGMhHf3FA++a1/EdW1Djt25mZToVCob5QTjnx/dh+yLegAAAA==
    Metadata:
      aws:cdk:path: HelloCdkGoStack/CDKMetadata/Default
    Condition: CDKMetadataAvailable
Conditions:
  …

This application has several resources already defined. Next examine hello-cdk-go.go where you will find the code that produced the preceeding.

package main

import (
    "github.com/aws/aws-cdk-go/awscdk"
    "github.com/aws/aws-cdk-go/awscdk/awssns"
    "github.com/aws/constructs-go/constructs/v3"
    "github.com/aws/jsii-runtime-go"
)

type HelloCdkGoStackProps struct {
    awscdk.StackProps
}

func NewHelloCdkGoStack(scope constructs.Construct, id string, props *HelloCdkGoStackProps) awscdk.Stack {
    var sprops awscdk.StackProps
    if props != nil {
        sprops = props.StackProps
    }
    stack := awscdk.NewStack(scope, &id, &sprops)

    // The code that defines your stack goes here

    // as an example, here's how you would define an AWS SNS topic:
    awssns.NewTopic(stack, jsii.String("MyTopic"), &awssns.TopicProps{
        DisplayName: jsii.String("MyCoolTopic"),
    })

    return stack
}

func main() {
    app := awscdk.NewApp(nil)

    NewHelloCdkGoStack(app, "HelloCdkGoStack", &HelloCdkGoStackProps{
        awscdk.StackProps{
            Env: env(),
        },
    })

    app.Synth(nil)
}

// env determines the AWS environment (account+region) in which our stack is to
// be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html
func env() *awscdk.Environment {
    // If unspecified, this stack will be "environment-agnostic".
    // Account/Region-dependent features and context lookups will not work, but a
    // single synthesized template can be deployed anywhere.
    //---------------------------------------------------------------------------
    return nil

    // Uncomment if you know exactly what account and region you want to deploy
    // the stack to. This is the recommendation for production stacks.
    //---------------------------------------------------------------------------
    // return &awscdk.Environment{
    //  Account: jsii.String("123456789012"),
    //  Region:  jsii.String("us-east-1"),
    // }

    // Uncomment to specialize this stack for the AWS Account and Region that are
    // implied by the current CLI configuration. This is recommended for dev
    // stacks.
    //---------------------------------------------------------------------------
    // return &awscdk.Environment{
    //  Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")),
    //  Region:  jsii.String(os.Getenv("CDK_DEFAULT_REGION")),
    // }
}

This file defines our program’s main function. It also imports the github.com/aws/aws-cdk-go/awscdk packages and then defines a few functions. Examine the main function first.

func main() {
    app := awscdk.NewApp(nil)

    NewHelloCdkGoStack(app, "HelloCdkGoStack", &HelloCdkGoStackProps{
        awscdk.StackProps{
            Env: env(),
        },
    })

    app.Synth(nil)
}

Here the awscdk.NewApp function is called which initializes the CDK app.

The documentation for this function indicates that it returns a struct implementing the App interface. This interface is then passed to the NewHelloCdkGoStack function along with the “HelloCdkGoStack” id and an instance of the HelloCdkGoStackProps struct. If you examine this function further, you will notice what it is doing with these arguments.

func NewHelloCdkGoStack(scope constructs.Construct, id string, props *HelloCdkGoStackProps) awscdk.Stack {
    var sprops awscdk.StackProps
    if props != nil {
        sprops = props.StackProps
    }
    stack := awscdk.NewStack(scope, &id, &sprops)

    // The code that defines your stack goes here

    // as an example, here's how you would define an AWS SNS topic:
    awssns.NewTopic(stack, jsii.String("MyTopic"), &awssns.TopicProps{
        DisplayName: jsii.String("MyCoolTopic"),
    })

    return stack
}

From here you can see that NewHelloCdkGoStack extracts the embedded awscdk.StackProps struct from its own props argument and passes it down when creating a new Stack. Then it creates a new SNS Topic with the id “MyTopic” and a name of “MyCoolTopic”.

You will also notice that NewHelloCdkGoStack accepts a struct implementing the constructs.Construct interface. If you follow the documentation, you will notice that awscdk.App embeds awscdk.Stage which in turn embeds constructs.Construct.

The AWS CDK in Go uses interfaces to model constructs and provides factory functions for creating new instances of objects that implement these interfaces. When navigating the documentation, if you encounter an interface type InterfaceName, there is always an exported function called NewInterfaceName for acquiring one. awscdk.NewStack returns an implementation of awscdk.Stack and awslambda.NewFunction returns an implementation of awslambda.Function.

You may also notice the frequent usage of pointer types. Pointer types are used to allow for optionality which Go does not natively support. There are convenience functions provided by the jsii Go Runtime to make passing pointer types a little more ergonomic. You can see the usage of these functions above with jsii.String, which accepts a string a returns a pointer to that string. This removes the need for allocating a variable in order to point to it just to pass a literal value that would otherwise be inline.

Both of these patterns may feel familiar to Go users, but for more information about why aws-cdk-go is modeled this way, check out the Go Language Bindings RFC.

Deploying Your App

Now that you know what the example app contains, you can deploy it to your AWS account using the deploy command of the AWS CDK CLI. First, make sure you have credentials configured to allow your local environment to deploy to your intended account. Instructions for configuring credentials can be found in the User Guide for the AWS CLI. Then you can run the cdk deploy command.

HelloCdkGoStack: deploying...
HelloCdkGoStack: creating CloudFormation changeset...
[█████████████████████████████████████████████] (3/3)
 ✅  HelloCdkGoStack

Stack ARN:
arn:aws:cloudformation:REGION:000000000000:stack/HelloCdkGoStack/00000000-0000-0000-0000-000000000000

Now that your stack is deployed, feel free to examine the AWS CDK Reference Documentation for constructs that you can add to your stack. Each construct has a corresponding interface that can be found in the Go documentation on pkg.go.dev.

Clean Up

After a successful deployment, you can inspect the created resources in your account. When you are ready to delete the test stack you can run the cdk destroy command from your terminal.

$ cdk destroy
Are you sure you want to delete: HelloCdkGoStack (y/n)? y
HelloCdkGoStack: destroying...
10:18:56 AM | DELETE_IN_PROGRESS   | AWS::CloudFormation::Sta
ck | HelloCdkGoStack

 ✅  HelloCdkGoStack: destroyed

Conclusion

In this post, you learned how to initialize and deploy a CDK Go application, as well as the basics of using the AWS CDK go module to define your own stacks and resources. We are excited to see what Gophers build using the CDK!

A lot of the code examples in the CDK reference documentation and developer guide are translated between supported languages. We are working on updating these examples to add Go translations. In the meantime, here are some basic guidelines to help map CDK APIs to Go.

  • Instantiate constructs using the NewConstructName factory functions
  • Construct props are go structs that can be constructed using struct literals
  • Use the pointer helper functions to pass primitive literal values to construct props (IE: jsii.String)

For more information about using the CDK with Go, check out the following documentation sites.

Since Go support is in Developer Preview, we are expecting to discover bugs and there are some known issues that the team is still fixing. If you’re interested in reporting new bugs, or helping to fix existing bugs, check out the new project board tracking work towards general availability. Also join the community on the cdk.dev slack channel to discuss your experience using the AWS CDK with Go.