Introduction to Serverless Functions in Go with AWS Lambda
\nServerless architecture has become the standard for building scalable and cost-effective applications. AWS Lambda is one of the leaders in this field, and Go (Golang) is an ideal language for writing serverless functions due to its performance, fast startup, and small binary size. In this article, we will cover the full workflow: from creating a simple function to deployment and monitoring.
\nWhy Go? Unlike Node.js or Python, Go compiles into a native binary file, which reduces cold start to tens of milliseconds. This is critically important for high-load systems.
\n\nMain Section
\n\n1. Creating and Structuring a Lambda Function in Go
\nAny Lambda function in Go starts with importing the github.com/aws/aws-lambda-go/lambda package. Let's look at a minimal example:
package main\n\nimport (\n "github.com/aws/aws-lambda-go/lambda"\n)\n\ntype MyEvent struct {\n Name string `json:"name"`\n}\n\ntype MyResponse struct {\n Message string `json:"message"`\n}\n\nfunc HandleRequest(event MyEvent) (MyResponse, error) {\n return MyResponse{Message: "Hello, " + event.Name + "!"}, nil\n}\n\nfunc main() {\n lambda.Start(HandleRequest)\n}\n\nKey points:
\n- \n
- Handler is the function that AWS Lambda calls. It can accept and return any data types (structs, strings, interfaces). \n
- Context is an optional first argument:
func HandleRequest(ctx context.Context, event MyEvent) (MyResponse, error). It allows canceling execution on timeout. \n - An error signals to Lambda that execution has failed. \n
2. Handling Events from Different AWS Services
\nLambda is often used as a trigger for events from S3, DynamoDB, SQS, and API Gateway. Go supports all event types through the github.com/aws/aws-lambda-go/events package.
Example for API Gateway (HTTP request):
\npackage main\n\nimport (\n "github.com/aws/aws-lambda-go/lambda"\n "github.com/aws/aws-lambda-go/events"\n)\n\nfunc handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {\n return events.APIGatewayProxyResponse{\n Body: "Hello, World!",\n StatusCode: 200,\n Headers: map[string]string{"Content-Type": "text/plain"},\n }, nil\n}\n\nfunc main() {\n lambda.Start(handler)\n}\n\nExample for S3 (new object in bucket):
\npackage main\n\nimport (\n "context"\n "fmt"\n "github.com/aws/aws-lambda-go/lambda"\n "github.com/aws/aws-lambda-go/events"\n)\n\nfunc handler(ctx context.Context, s3Event events.S3Event) error {\n for _, record := range s3Event.Records {\n bucket := record.S3.Bucket.Name\n key := record.S3.Object.Key\n fmt.Printf("New file: %s in bucket %s\\n", key, bucket)\n }\n return nil\n}\n\nfunc main() {\n lambda.Start(handler)\n}\n- \n
- Use
events.S3Event,events.SNSEvent,events.DynamoDBEvent, and others. \n - For custom events (e.g., from CloudWatch), use
json.Unmarshal. \n
3. Compilation, Deployment, and Best Practices
\nGo compiles for Linux (x86_64 or arm64 architecture). Build the binary for Lambda:
\n# For x86_64\nGOOS=linux GOARCH=amd64 go build -o bootstrap main.go\n\n# For ARM (Graviton) — cheaper and faster\nGOOS=linux GOARCH=arm64 go build -o bootstrap main.go\n\nThen package it into a ZIP and upload via AWS CLI or console:
\nzip function.zip bootstrap\naws lambda create-function \\\n --function-name my-go-function \\\n --runtime provided.al2023 \\\n --role arn:aws:iam::XXXXXXXXXXX