Introduction
In today's world of cloud computing, AWS Lambda is a serverless, event-driven compute service that lets you run code for virtually any type of application or backend service without provisioning or managing servers. You can trigger Lambda from over 200 AWS services and software as a service (SaaS) applications, and only pay for what you use.
Go is a statically typed, compiled language known for its simplicity, efficiency, and ease of use. It's particularly well-suited for building scalable and efficient cloud services.
In this guide, I will demonstrate how to deploy a Go API server on AWS Lambda step by step.
Creating a Lambda Function
First, you need to create a new Lambda function. Log into your AWS console and navigate to the Lambda service. Click the 'Create function' button. You will see many options, but don't worry, we only need to adjust a few. Leaving the rest as they are will be sufficient to host our Go server.
- Enter your function name. For example, I used
go-api
. You should use a name that is meaningful. - Select the runtime. In this case, we'll choose
Amazon Linux 2023
. - Optionally, if you're building a Go application for ARM, you should change the Architecture to arm64.
- Click to open Advanced settings and enable the
function URL
. This function is powerful and easy to use, and we will be using it. - Setting the
Auth type
toNONE
simplifies its use. For enhanced security, you could useAWS_IAM
, but that's a different topic that we won't discuss here.
Edit the Go Source Code
Next, we need to create a minimal Go function for AWS Lambda. Here's a sample main.go
.
- We import
github.com/aws/aws-lambda-go/lambda
. This dependency is necessary for running Go as a Lambda function. - In the
main
function, we uselambda.Start
to start the handler.
package main
import (
"context"
"fmt"
"github.com/aws/aws-lambda-go/lambda"
)
type RequestEvent struct {
RawPath string `json:"rawPath"`
RawQueryString string `json:"rawQueryString"`
Body string `json:"body"`
}
func HandleRequest(ctx context.Context, event *RequestEvent) (*string, error) {
if event == nil {
return nil, fmt.Errorf("received nil event")
}
message := fmt.Sprintf(
"RawPath: %s, RawQueryString: %s, Body: %s",
event.RawPath, event.RawQueryString, event.Body,
)
return &message, nil
}
func main() {
lambda.Start(HandleRequest)
}
Next, we need to compile the main into a binary. Simply copy the following command line, ensuring the output filename is 'bootstrap'.
GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o bootstrap main.go
Next, we need to compress the bootstrap file into a zip format. Without doing this, we cannot upload it to AWS Lambda. Be sure to place the bootstrap file at the root of the zip file.
zip myFunction.zip bootstrap
We've now set up the basic Go application. It's time to upload and conduct a test.
Upload to AWS lambda
Click to enter the lambda function we created previously and scroll down. Find the Code Source
block within the code tab. To the right of this block, click the Upload from
button and select the .zip file
option. Locate your zip file and upload it.
After uploading, you should find information similar to the details below the Code Source
block. This indicates that your upload was successful.
Test the function
Scroll up, and on the right of Function overview
, you'll find the function URL
. This is the advanced option we just set. The function URL
is a powerful tool that can convert your RESTful requests into lambda handler requests, and then encode the handler output into a RESTful response. It's particularly useful for building API servers based on lambda.
Click the small copy button to duplicate the URL. You can now use curl
to test your lambda function. Input this command into your terminal and press enter. Remember, you need to replace the function URL
with your own.
curl -XPOST 'https://{your_lambda_function_URL}/hello?
name=world' -H 'Content-Type: application/json' --data '{"age": 16}'
The magic happens, you should see the output like this:
RawPath: /hello, RawQueryString: name=world, Body: {"age": 16}
Review the codes again, and you'll find the structure. This structure is the second parameter of the handler. The magic here is that the lambda library decodes the path, query string, and body into our structure. While many other fields are available, these three are the most crucial.
type RequestEvent struct {
RawPath string `json:"rawPath"`
RawQueryString string `json:"rawQueryString"`
Body string `json:"body"`
}