Package: aws-cdk.aws-lambda-go-alpha
Amazon Lambda Golang Library---The APIs of higher level constructs in this module are experimental and under active development.
They are subject to non-backward compatible changes or removal in any future version. These are
not subject to theSemantic Versioningmodel and breaking changes will be
announced in the release notes. This means that while you may use them, you may need to update
your source code when upgrading to a newer version of this package.This library provides constructs for Golang Lambda functions.To use this module you will either need to haveGoinstalled (go1.11or later) orDockerinstalled.
SeeLocal Bundling/Docker Bundlingfor more information.This module also requires that your Golang application is
using a Go version >= 1.11 and is usingGo modules.Go FunctionDefine aGoFunction:go.GoFunction(self,"handler",entry="app/cmd/api")By default, ifentrypoints to a directory, then the construct will assume there is a Go entry file (i.e.main.go).
Let's look at an example Go project:lamda-app
├──cmd
│└──api
│└──main.go
├──go.mod
├──go.sum
├──pkg
│├──auth
││└──auth.go
│└──middleware
│└──middleware.go
└──vendor├──github.com│└──aws│└──aws-lambda-go└──modules.txtWith the above layout I could either provide theentryaslambda-app/cmd/apiorlambda-app/cmd/api/main.go, either will work.
When the construct builds the golang binary this will be translatedgo build ./cmd/api&go build ./cmd/api/main.gorespectively.
The construct will figure out where it needs to run thego buildcommand from, in this example it would be from
thelambda-appdirectory. It does this by determining themod file path, which is explained in the
next section.mod file pathTheGoFunctiontries to automatically determine your project root, that is
the root of your golang project. This is usually where the top levelgo.modfile orvendorfolder of your project is located. When bundling in a Docker container, themoduleDiris used as the source (/asset-input) for the volume mounted in
the container.The CDK will walk up parent folders starting from
the current working directory until it finds a folder containing ago.modfile.Alternatively, you can specify themoduleDirprop manually. In this case you
need to ensure that this path includesentryand any module/dependencies used
by your function. Otherwise bundling will fail.RuntimeTheGoFunctioncan be used with either theGO_1_Xruntime or the provided runtimes (PROVIDED/PROVIDED_AL2).
By default it will use thePROVIDED_AL2runtime. TheGO_1_Xruntime does not support things likeLambda Extensions, whereas the provided runtimes do.
Theaws-lambda-golibrary has built in support for the provided runtime as long as
you name the handlerbootstrap(which we do by default).DependenciesThe construct will attempt to figure out how to handle the dependencies for your function. It will
do this by determining whether or not you are vendoring your dependencies. It makes this determination
by looking to see if there is avendorfolder at themod file path.With this information the construct can determine what commands to run. You will
generally fall into two scenarios:You are using vendoring (indicated by the presence of avendorfolder)
In this casego buildwill be run with-mod=vendorsetYou are not using vendoring (indicated by the absence of avendorfolder)
If you are not vendoring thengo buildwill be run without-mod=vendorsince the default behavior is to download dependenciesAll other properties oflambda.Functionare supported, see also theAWS Lambda construct library.EnvironmentBy default the following environment variables are set for you:GOOS=linuxGOARCH: based on the target architecture of the Lambda functionGO111MODULE=onUse theenvironmentprop to define additional environment variables when go runs:go.GoFunction(self,"handler",entry="app/cmd/api",bundling=go.BundlingOptions(environment={"HELLO":"WORLD"}))Local BundlingIfGois installed locally and the version is >=go1.11then it will be used to bundle your code in your environment. Otherwise, bundling will happen in aLambda compatible Docker containerwith the Docker platform based on the target architecture of the Lambda function.For macOS the recommended approach is to installGoas Docker volume performance is really poor.Gocan be installed by following theinstallation docs.DockerTo force bundling in a docker container even ifGois available in your environment, set theforceDockerBundlingprop totrue. This is useful if you want to make sure that your function is built in a consistent Lambda compatible environment.Use thebuildArgsprop to pass build arguments when building the bundling image:go.GoFunction(self,"handler",entry="app/cmd/api",bundling=go.BundlingOptions(build_args={"HTTPS_PROXY":"https://127.0.0.1:3001"}))Use thebundling.dockerImageprop to use a custom bundling image:go.GoFunction(self,"handler",entry="app/cmd/api",bundling=go.BundlingOptions(docker_image=DockerImage.from_build("/path/to/Dockerfile")))Use thebundling.goBuildFlagsprop to pass additional build flags togo build:go.GoFunction(self,"handler",entry="app/cmd/api",bundling=go.BundlingOptions(go_build_flags=["-ldflags\"-s -w\""]))By default this construct doesn't use any Go module proxies. This is contrary to
a standard Go installation, which would use the Google proxy by default. To
recreate that behavior, do the following:go.GoFunction(self,"GoFunction",entry="app/cmd/api",bundling=go.BundlingOptions(go_proxies=[go.GoFunction.GOOGLE_GOPROXY,"direct"]))You can set additional Docker options to configure the build environment:go.GoFunction(self,"GoFunction",entry="app/cmd/api",bundling=go.BundlingOptions(network="host",security_opt="no-new-privileges",user="user:group",volumes_from=["777f7dc92da7"],volumes=[DockerVolume(host_path="/host-path",container_path="/container-path")]))Command hooksIt is  possible to run additional commands by specifying thecommandHooksprop:// This example only available in TypeScript
// Run additional commands on a GoFunction via `commandHooks` property
new go.GoFunction(this, 'handler', {
  bundling: {
    commandHooks: {
      // run tests
      beforeBundling(inputDir: string): string[] {
        return ['go test ./cmd/api -v'];
      },
      // ...
    },
  },
});The following hooks are available:beforeBundling: runs before all bundling commandsafterBundling: runs after all bundling commandsThey all receive the directory containing thego.modfile (inputDir) and the
directory where the bundled asset will be output (outputDir). They must return
an array of commands to run. Commands are chained with&&.The commands will run in the environment in which bundling occurs: inside the
container for Docker bundling or on the host OS for local bundling.Additional considerationsDepending on how you structure your Golang application, you may want to change theassetHashTypeparameter.
By default this parameter is set toAssetHashType.OUTPUTwhich means that the CDK will calculate the asset hash
(and determine whether or not your code has changed) based on the Golang executable that is created.If you specifyAssetHashType.SOURCE, the CDK will calculate the asset hash by looking at the folder
that contains yourgo.modfile. If you are deploying a single Lambda function, or you want to redeploy
all of your functions if anything changes, thenAssetHashType.SOURCEwill probably work.For example, if my app looked like this:lamda-app
├──cmd
│└──api
│└──main.go
├──go.mod
├──go.sum
└──pkg└──auth└──auth.goWith this structure I would provide theentryascmd/apiwhich means that the CDK
will determine that the protect root islambda-app(it contains thego.modfile).
Since I only have a single Lambda function, and any update to files within thelambda-appdirectory
should trigger a new deploy, I could specifyAssetHashType.SOURCE.On the other hand, if I had a project that deployed multiple Lambda functions, for example:lamda-app
├──cmd
│├──api
││└──main.go
│└──anotherApi
│└──main.go
├──go.mod
├──go.sum
└──pkg├──auth│└──auth.go└──middleware└──middleware.goThen I would most likely wantAssetHashType.OUTPUT. WithOUTPUTthe CDK will only recognize changes if the Golang executable has changed,
and Go only includes dependencies that are used in the executable. So in this case
ifcmd/apiused theauth&middlewarepackages, butcmd/anotherApidid not, then
an update toauthormiddlewarewould only trigger an update to thecmd/apiLambda
Function.Docker based bundling in complex Docker configurationsBy default the input and output of Docker based bundling is handled via bind mounts.
In situtations where this does not work, like Docker-in-Docker setups or when using a remote Docker socket, you can configure an alternative, but slower, variant that also works in these situations.go.GoFunction(self,"GoFunction",entry="app/cmd/api",bundling=go.BundlingOptions(bundling_file_access=BundlingFileAccess.VOLUME_COPY))