This page looks best with JavaScript enabled

AWS Lambda function in GO

 ·  ☕ 7 min read  ·  ✍️ Neeraj Sidhaye · 👀... views

In this post, we will be creating, deploying and invoking a aws lambda function in Go.

We will be using AWS CLI throughout this post for

  • Creating role ( aws iam create-role )
  • Attaching policy to the role ( aws iam attach-role-policy )
  • Deploying Lambda function ( aws lambda create-function )
  • Invoking the lambda function ( aws lambda invoke )

Our lambda function will return a account detail json as below.

{“id”: “23090”, “type”: “current”, “accountNum”: “45387954”, “sortCode”: “20-98-99”}

Let’s start step by step

Coding lambda function in GO

Let’s create our project repo named “accounts”.
Navigate to your GO workspace and create a folder named “accounts”

$ mkdir accounts && cd accounts

Creating main.go

Create main.go file

$ touch main.go

Now we will need to download aws go lambda package, so that we can use aws lambda libraries in our main.go code.

$ go get github.com/aws/aws-lambda-go/lambda

when we run this, go downloads libraries into your

%GOPATH%/pkg\mod\github.com\aws\

We can run $ go env GOPATH to check environment variable to find out where these aws lambda libraries is getting downloaded.

Ok, so by now we have an empty main.go and aws lambda libraries downloaded.

Let’s create our lambda function.

  1. Create a simple account struct with account details ( id, type, accountNum and sortcode)

  2. Write a lambda handler which will initialize and return a new account object.

  3. Call a lambda handler from main function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main

import (

	"github.com/aws/aws-lambda-go/lambda"
)

// 1- creating account struct
type account struct{

	ID string `json:"id"`
	Type string `json:"type"`
	AccNum string `json:"accountNum"`
	SortCode string `json:"sortCode"`
}

// 2 - lambda handler - initializing and returning account object
func showAccount() (*account, error) {

	account := &account{
		ID: "23456",
		Type: "current",
		AccNum: "45328976",
		SortCode: "30-89-99",
	}
	return account, nil
}

func main(){

	// 3 - calling lambda handler
	lambda.Start(showAccount)
}

Lambda Handlers

In the above code, function showAccount is a lambda handler.
There are various signature available for lambda handler.

The one we are using is func() (TOut, error)
Tin and Tout parameters are object that can be marshalled or unmarshalled using Go encoding/json package.

func ()
func () error
func (TIn) error
func () (TOut, error)
func (context.Context) error
func (context.Context, TIn) error
func (context.Context) (TOut, error)
func (context.Context, TIn) (TOut, error)

🔆 Have a look at AWS Lambda function handler in Go and refer to section Valid handler signatures.

Creating go.mod

Running go mod init <module-name> and then run go mod tidy command to download the dependencies required by source file.

$ go mod init github.com/neerajsidhaye/go-modules-examples

$ go mod tidy

We will now have a go.mod file created with below contents

1
2
3
4
5
6
7
module github.com/neerajsidhaye/go-modules-examples

go 1.16

require github.com/aws/aws-lambda-go v1.26.0


Creating build executable and ZIP for AWS

We will now create an executable for account package using go build.

$ env GOOS=linux GOARCH=amd64 go build -o main D:/dev/go-workspace/accounts

This command will create an executable with name main in the current directory. You can provide any path for executable.

We have used env for setting up two environment variables (GOOS=linux and GOARCH=amd64). This instructs go compiler to create an executable compatible for linux OS and amd64 architecture. This is what we will be using while deploying on AWS.

creating zip file of executable

AWS requires lambda function to deploy in a zip file format. The executable must be in the root of the zip file.

On windows, zip file can be created in PowerShell with below command

compress-archive <output.zip>

compress-archive main main.zip

this will create main.zip file which will have main executable at the root of zip.

AWS CLI configuration

Install CLI

First you need to install AWS CLI. If you don’t have it, you can refer here for windows download instruction Installing, updating, and uninstalling the AWS CLI version 2 on Windows

$ aws --version
this will tell, which version of aws cli you have. Example:-

aws-cli/2.2.8 Python/3.8.8 Windows/10 exe/AMD64 prompt/off

Setup IAM user for the CLI to use

We need to create a IAM user with Programmatic access permission for the CLI to use.
Refer here for Creating IAM user

For testing purpose, we can create a IAM user and attach AdministratorAccess policy to this user.

In practice, we must always attach a more restrictive policy to a user.

Configure CLI

We will need to configure CLI to use credentials of IAM user we just created.

Input access-key-Id and secret-access-Key of the IAM user you have crated with admin policy attached.

$ aws configure
AWS Access Key ID [none]: <input access-key-ID>
AWS Secret Access Key [none]: <input secret-access-key>
Default region name [none]: eu-west-2
Default output format [none]: json

Creating IAM role for Lambda Function

We will now have to create an IAM role which defines permission that our lambda function will have when it’s running.

We will create a role called lambda-accounts-executor and attach AWSLambdaBasicExecutionRole managed policy to it.
This role ( lambda-accounts-executor ) will now give our lambda function a basic permission it need to run.

Creating a trust policy

Create a file called, trust-policy.json

This trust policy will instruct AWS to allow lambda services to assume the lambda-accounts-executor role.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

Create IAM Role

Creating role “lambda-accounts-executor” with trust policy

$ aws iam create-role --role-name lambda-accounts-executor --assume-role-policy-document file://D:/Tech/AWS/golambda-user/trust-policy.json
 

We will have result like below. We will need Arn value in next step while deploying the lambda function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

{
    "Role": {
        "Path": "/",
        "RoleName": "lambda-accounts-executor",
        "RoleId": "AROATR36XMNXTAIYYCOPR",
        "Arn": "arn:aws:iam::<account-id>:role/lambda-accounts-executor",
        "CreateDate": "2021-09-04T23:42:28+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}

Attach policy to the role

We have role (lambda-accounts-executor) created and now we will need to specify the permission the role has. We can do this by attaching a policy to the role.

$ aws iam attach-role-policy --role-name lambda-accounts-executor --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

We have used aws iam attach-role-policy command, passing in the ARN of AWSLambdaBasicExecutionRole permission policy.

Deploy lambda function

Now we are ready to deploy our lambda function.

We will use command aws lambda create-function and which takes following parameters

–function name - Name of the lambda function called within AWS

–runtime - The runtime environment for the lambda function

–role - The ARN of the role you want the lambda function to assume when it is running.

–handler - The of the executable in the root of the zip file.

–zip-file - Path to the zip file.

$ aws lambda create-function --function-name accounts --runtime go1.x --role arn:aws:iam::<account-id>:role/lambda-accounts-executor --handler main --zip-file fileb://D:/dev/go-workspace/accounts/main.zip

We should see output like as below

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "FunctionName": "accounts",
    "FunctionArn": "arn:aws:lambda:eu-west-2:<account-id>:function:accounts",
    "Runtime": "go1.x",
    "Role": "arn:aws:iam::<account-id>:role/lambda-accounts-executor",
    "Handler": "main",
    "CodeSize": 4301831,
    "Description": "",
    "Timeout": 3,
    "MemorySize": 128,
    "LastModified": "2021-09-05T00:07:07.466+0000",
    "CodeSha256": "9S2jsLAgT0YW6QvqGe0PjNgAK0ClI4S5fY/+xrcMLII=",
    "Version": "$LATEST",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "ed7f4a67-5ffb-4dbb-850a-089b4c98127b",
    "State": "Active",
    "LastUpdateStatus": "Successful",
    "PackageType": "Zip"
}

That’s all, our lambda function is deployed successfully.

Invoking lambda function

We can use command aws lambda invoke , which ask for output file name for the response.

$ aws lambda invoke --function-name accounts output.json
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}

output.json gets created and it’s content is as below. This is exactly what our showAccount function in main.go is returning.

1
2
3

{"id":"23456","type":"current","accountNum":"45328976","sortCode":"30-89-99"}

Share on

{Neeraj:Sidhaye}
WRITTEN BY
Neeraj Sidhaye
I Aspire to Inspire before I Expire!