How to Create & Deploy AWS Lambda Function in Go

Updated on
gopher going through tunnel to lambda

AWS Lambda is a serverless compute platform where you write code in your favorite programming language, without worrying about setting up a virtual machine. You pay only for the invocations and the time (milliseconds) till which your Lambda function runs for.

Most of us know JavaScript & Python, but they’re not as memory efficient as compiled languages. We can use an easy-to-use, compiled language like Go.

Benefits of using Go in AWS Lambda

Although AWS Lambda supports many runtimes like Java, .NET, NodeJS, Python, Amazon Linux and Ruby, here’s why Golang takes the cake:

  • Faster startup time
  • Compiled language
  • Type safe runtime
  • Low memory usage

With these, you reduce your costs (while providing a faster experience), and your customers stay happy.

Install Go in your OS

You can download and install Go from the download page.

Install Go in Arch Linux

yay -S go

Install Go via Homebrew in MacOS

brew install go

Install Go with winget in Windows

winget install go

Create a Hello World Go project

  • Create a directory for your Go Lambda project
  • Run go mod init learnaws.io to create a mod file
  • Create a new file called main.go

Let’s write a simple Println().

package main

import "fmt"

func main() {
	fmt.Println("Hello from LearnAWS.io")
}

Run it with go run .

You’ll get this message in output:

 go run .
Hello from LearnAWS.io

The Gopher helloes you back.

Basic AWS Lambda Go function

Install aws-lambda-go package

Using go get we can install the dependency in our project

 go get github.com/aws/aws-lambda-go
go: added github.com/aws/aws-lambda-go v1.46.0

Hello world function

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

func handleRequest() (string, error) {
	return "Hello there my fried friend", nil
}

func main() {
	lambda.Start(handleRequest)
}

Build & Compile the Lambda Go function

Compile Go code for arm64 Linux

We set the architecture to arm64 and OS to Linux

GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o bootstrap main.go

Zip the go binary file

Use the zip utility which comes prebuilt.

zip lambda-handler.zip bootstrap

Your output will look something like this

adding: bootstrap (deflated 46%)

Create a Lambda function with AL2023 Runtime

Let’s create a Lambda function with Amazon Linux 2023 runtime and arm64 architecture.

Lambda console screenshot with Amazon Linux 2023 selected in the runtime

Enable function URL in advance settings with Auth type NONE: Lambda console screenshot showing how to enable function url while creating
Lambda function for Go

The Lambda function for Go is ready with function URL in the bottom right: Lambda console shows banner of successful function creation and Lambda
function URL

Upload zip to AWS Lambda

Upload the zip file by clicking on Upload from and select the bootstrap file which we zipped before.

AWS Lambda console bootstrapped zip uploaded

Test the response using the Function URL

You can simply visit the function URL link from your browser or curl it from your terminal.

This is the response with headers when making a request to our Lambda function URL:

< HTTP/1.1 200 OK
< Date: Thu, 04 Apr 2024 16:29:19 GMT
< Content-Type: application/json
< Content-Length: 27
Hello there my fried friend

Getting real with the request

Sending hello fried friend is not enough. We need to know how to retrieve information from request, and send more information with headers in the body.

Now we can update our request handler function with the actual types:


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

func handleRequest(
    ctx context.Context,
    req events.APIGatewayV2HTTPRequest
) (events.APIGatewayV2HTTPResponse, error) {
    // return your response now
}

Let’s get the client’s IP from the request and send it in the body

// we make body a string and append IP using `Sprintf`
body := fmt.Sprintf("Fella your IP is %s", req.RequestContext.HTTP.SourceIP)

//  tell the HTTP client this is not default JSON it's text
headers := map[string]string{
	"Content-Type": "text/plain",
}

Send JSON from Go AWS Lambda

We can create a string map like JavaScript object and use json.Marshal to encode the object/map into JSON string.

body := map[string]interface{}{
    "message": "Learn AWS the way you want",
    // get AWS region from Lambda environment variables
    "region":  os.Getenv("AWS_REGION"),
    // get current time and format it
    "time":    time.Now().Format(time.Kitchen),
}

// encode the object into json (Stringify)
jsonBody, jsonErr := json.Marshal(body)

Send JSON Content-Type header:

headers := map[string]string{
    "Content-Type": "application/json",
}

return events.APIGatewayV2HTTPResponse{
    Body:       out.String(),
    StatusCode: 200,
    Headers:    headers,
}, jsonErr

The complete Go code looks like this:

package main

import (
	"context"
	"encoding/json"
	"os"
	"time"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

type Body struct {
	message string
	region  string
	time    int64
}

// time format "01/02/2006 03:04:05 PM (MST)"
func handleRequest(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) {

	body := map[string]interface{}{
		"message": "Learn AWS the way you want",
		"region":  os.Getenv("AWS_REGION"),
		"time":    time.Now().Format(time.Kitchen),
	}

	jsonBody, jsonErr := json.Marshal(body)

	headers := map[string]string{
		"Content-Type": "application/json",
	}

	return events.APIGatewayV2HTTPResponse{
		Body:       string(jsonBody),
		StatusCode: 200,
		Headers:    headers,
	}, jsonErr
}

func main() {
	lambda.Start(handleRequest)
}

Now when you make an HTTP request to your Lambda function URL or API Gateway you will receive the following response:

HTTP/1.1 200 OK
Date: Fri, 05 Apr 2024 16:28:57 GMT
Content-Type: application/json
Content-Length: 87
Connection: keep-alive
x-amzn-RequestId: 81062e64-1ab1-4126-aaa7-1aef4e4bcf53
X-Amzn-Trace-Id: root=1-661026c9-5410df683c0fc134555ab9a8;parent=5a395cd09f4d868b;sampled=0;lineage=ef83c937:0

{
	"message": "Learn AWS the way you want",
	"region": "us-east-1",
	"time": "4:28PM"
}

Automate deployment with AWS CLI & Makefile

To update the Lambda code we do the perform the following operations manually every time:

  1. Compile the Go output
  2. Zip the bootstrap file
  3. Go to Lambda console
  4. Click on Upload zip
  5. Select the zip file
  6. Click on Save

and of course wait for a while …

What if I told you, you can perform all the above steps by just running one command from your terminal.

big makefile daddy standing while the small zipper doggy cries using AWS console and zipping file

Makefile solves this exact problem

Caution

You need to have AWS CLI installed to use the Makefile to update Lambda code. Don’t know how to set it up? Learn to setup AWS CLI

Tip

Install make on Windows with winget: winget install ezwinports.make

On *nix based distro make comes pre installed.

Makefile for building & updating arm64 Lambda

// Put your function name
FUNCTION_NAME=my-go-lambda-fn

// Set the GOARCH to your Lambda architecture (amd64 for x86)
build:
	GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o bootstrap main.go
	zip lambda-handler.zip bootstrap

update_lambda: build
	aws lambda update-function-code --function-name $(FUNCTION_NAME) --zip-file fileb://lambda-handler.zip > /dev/null

Now to update your Lambda from your CLI all you gotta do is run:

make update_lambda

Wait for few seconds … Your Lambda function is now updated with the latest code which you wrote in main.go Yeah, it was that simple.

Tip

If you just want to build the zip you can run make build

What’s next?

Now you’ve learnt how to use Go with AWS Lambda you can start to build amazing things on serverless.

Tip

I’ll leave you with the list of amazing Go libraries so you can build something cool with Go on AWS Lambda.

Got any questions or suggestions? Leave them below in the comments.

That’s all for this tutorial my friend. I hope you learnt something new and fun.

Don’t forget to share this article on your social media ;)


Hills 🏔 and Skills, What's Common?

They both need you to be on top.

You will get lifetime access with:

All yours, just at:

$149

Just type and your search result will magically appear here