A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://docs.aws.amazon.com/lambda/latest/dg/golang-handler.html below:

Define Lambda function handlers in Go

Define Lambda function handlers in Go

The Lambda function handler is the method in your function code that processes events. When your function is invoked, Lambda runs the handler method. Your function runs until the handler returns a response, exits, or times out.

This page describes how to work with Lambda function handlers in Go, including project setup, naming conventions, and best practices. This page also includes an example of a Go Lambda function that takes in information about an order, produces a text file receipt, and puts this file in an Amazon Simple Storage Service (Amazon S3) bucket. For information about how to deploy your function after writing it, see Deploy Go Lambda functions with .zip file archives or Deploy Go Lambda functions with container images.

Setting up your Go handler project

A Lambda function written in Go is authored as a Go executable. You can initialize a Go Lambda function project the same way you initialize any other Go project using the following go mod init command:

go mod init example-go

Here, example-go is the module name. You can replace this with anything. This command initializes your project and generates the go.mod file that lists your project's dependencies.

Use the go get command to add any external dependencies to your project. For example, for all Lambda functions in Go, you must include the github.com/aws/aws-lambda-go/lambda package, which implements the Lambda programming model for Go. Include this package with the following go get command:

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

Your function code should live in a Go file. In the following example, we name this file main.go. In this file, you implement your core function logic in a handler method, as well as a main() function that calls this handler.

Example Go Lambda function code

The following example Go Lambda function code takes in information about an order, produces a text file receipt, and puts this file in an Amazon S3 bucket.

Example main.go Lambda function
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/s3"
)

type Order struct {
	OrderID string  `json:"order_id"`
	Amount  float64 `json:"amount"`
	Item    string  `json:"item"`
}

var (
	s3Client *s3.Client
)

func init() {
	// Initialize the S3 client outside of the handler, during the init phase
	cfg, err := config.LoadDefaultConfig(context.TODO())
	if err != nil {
		log.Fatalf("unable to load SDK config, %v", err)
	}

	s3Client = s3.NewFromConfig(cfg)
}

func uploadReceiptToS3(ctx context.Context, bucketName, key, receiptContent string) error {
	_, err := s3Client.PutObject(ctx, &s3.PutObjectInput{
		Bucket: &bucketName,
		Key:    &key,
		Body:   strings.NewReader(receiptContent),
	})
	if err != nil {
		log.Printf("Failed to upload receipt to S3: %v", err)
		return err
	}
	return nil
}

func handleRequest(ctx context.Context, event json.RawMessage) error {
	// Parse the input event
	var order Order
	if err := json.Unmarshal(event, &order); err != nil {
		log.Printf("Failed to unmarshal event: %v", err)
		return err
	}

	// Access environment variables
	bucketName := os.Getenv("RECEIPT_BUCKET")
	if bucketName == "" {
		log.Printf("RECEIPT_BUCKET environment variable is not set")
		return fmt.Errorf("missing required environment variable RECEIPT_BUCKET")
	}

	// Create the receipt content and key destination
	receiptContent := fmt.Sprintf("OrderID: %s\nAmount: $%.2f\nItem: %s",
		order.OrderID, order.Amount, order.Item)
	key := "receipts/" + order.OrderID + ".txt"

	// Upload the receipt to S3 using the helper method
	if err := uploadReceiptToS3(ctx, bucketName, key, receiptContent); err != nil {
		return err
	}

	log.Printf("Successfully processed order %s and stored receipt in S3 bucket %s", order.OrderID, bucketName)
	return nil
}

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

This main.go file contains the following sections of code:

For this function to work properly, its execution role must allow the s3:PutObject action. Also, ensure that you define the RECEIPT_BUCKET environment variable. After a successful invocation, the Amazon S3 bucket should contain a receipt file.

Handler naming conventions

For Lambda functions in Go, you can use any name for the handler. In this example, the handler method name is handleRequest. To reference the handler value in your code, you can use the _HANDLER environment variable.

For Go functions deployed using a .zip deployment package, the executable file that contains your function code must be named bootstrap. In addition, the bootstrap file must be at the root of the .zip file. For Go functions deployed using a container image, you can use any name for the executable file.

Defining and accessing the input event object

JSON is the most common and standard input format for Lambda functions. In this example, the function expects an input similar to the following:

{
    "order_id": "12345",
    "amount": 199.99,
    "item": "Wireless Headphones"
}

When working with Lambda functions in Go, you can define the shape of the expected input event as a Go struct. In this example, we define a struct to represent an Order:

type Order struct {
    OrderID string  `json:"order_id"`
    Amount  float64 `json:"amount"`
    Item    string  `json:"item"`
}

This struct matches the expected input shape. After you define your struct, you can write a handler signature that takes in a generic JSON type compatible with the encoding/json standard library. You can then deserialize it into your struct using the func Unmarshal function. This is illustrated in the first few lines of the handler:

func handleRequest(ctx context.Context, event json.RawMessage) error {
    // Parse the input event
    var order Order
    if err := json.Unmarshal(event, &order); err != nil {
        log.Printf("Failed to unmarshal event: %v", err)
        return err
    ...
}

After this deserialization, you can access the fields of the order variable. For example, order.OrderID retrieves the value of "order_id" from the original input.

Note

The encoding/json package can access only exported fields. To be exported, field names in the event struct must be capitalized.

Accessing and using the Lambda context object

The Lambda context object contains information about the invocation, function, and execution environment. In this example, we declared this variable as ctx in the handler signature:

func handleRequest(ctx context.Context, event json.RawMessage) error {
    ...
}

The ctx context.Context input is an optional argument in your function handler. For more information about accepted handler signatures, see Valid handler signatures for Go handlers.

If you make calls to other services using the AWS SDK, the context object is required in a few key areas. For example, to properly initialize your SDK clients, you can load the correct AWS SDK configuration using the context object as follows:

// Load AWS SDK configuration using the default credential provider chain
    cfg, err := config.LoadDefaultConfig(ctx)

SDK calls themselves may require the context object as an input. For example, the s3Client.PutObject call accepts the context object as its first argument:

// Upload the receipt to S3
    _, err = s3Client.PutObject(ctx, &s3.PutObjectInput{
        ...
    })

Outside of AWS SDK requests, you can also use the context object for function monitoring. For more information about the context object, see Using the Lambda context object to retrieve Go function information.

Valid handler signatures for Go handlers

You have several options when building a Lambda function handler in Go, but you must adhere to the following rules:

The following lists valid handler signatures. TIn and TOut represent types compatible with the encoding/json standard library. For more information, see func Unmarshal to learn how these types are deserialized.

Using the AWS SDK for Go v2 in your handler

Often, you'll use Lambda functions to interact with or make updates to other AWS resources. The simplest way to interface with these resources is to use the AWS SDK for Go v2.

Note

The AWS SDK for Go (v1) is in maintenance mode, and will reach end-of-support on July 31, 2025. We recommend that you use only the AWS SDK for Go v2 going forward.

To add SDK dependencies to your function, use the go get command for the specific SDK clients that you need. In the example code earlier, we used the config library and the s3 library. Add these dependencies by running the following commands in the directory that contains your go.mod and main.go files:

go get github.com/aws/aws-sdk-go-v2/config
go get github.com/aws/aws-sdk-go-v2/service/s3

Then, import the dependencies accordingly in your function's import block:

import (
    ...
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/s3"
)

When using the SDK in your handler, configure your clients with the right settings. The simplest way to do this is to use the default credential provider chain. This example illustrates one way to load this configuration:

// Load AWS SDK configuration using the default credential provider chain
    cfg, err := config.LoadDefaultConfig(ctx)
    if err != nil {
        log.Printf("Failed to load AWS SDK config: %v", err)
        return err
    }

After loading this configuration into the cfg variable, you can pass this variable into client instantiations. The example code instantiates an Amazon S3 client as follows:

// Create an S3 client
    s3Client := s3.NewFromConfig(cfg)

In this example, we initialized our Amazon S3 client in the init() function to avoid having to initialize it every time we invoke our function. The problem is that in the init() function, Lambda doesn't have access to the context object. As a workaround, you can pass in a placeholder like context.TODO() during the initialization phase. Later, when you make a call using the client, pass in the full context object. This workaround is also described in Using the context in AWS SDK client initializations and calls.

After you configure and initialize your SDK client, you can then use it to interact with other AWS services. The example code calls the Amazon S3 PutObject API as follows:

_, err = s3Client.PutObject(ctx, &s3.PutObjectInput{
    Bucket: &bucketName,
    Key:    &key,
    Body:   strings.NewReader(receiptContent),
})
Accessing environment variables

In your handler code, you can reference any environment variables by using the os.Getenv() method. In this example, we reference the defined RECEIPT_BUCKET environment variable using the following line of code:

// Access environment variables
    bucketName := os.Getenv("RECEIPT_BUCKET")
    if bucketName == "" {
        log.Printf("RECEIPT_BUCKET environment variable is not set")
        return fmt.Errorf("missing required environment variable RECEIPT_BUCKET")
    }
Using global state

To avoid creating new resources every time you invoke your function, you can declare and modify global variables outside of your Lambda function's handler code. You define these global variables in a var block or statement. In addition, your handler may declare an init() function that is executed during the initialization phase. The init method behaves the same in AWS Lambda as it does in standard Go programs.

Code best practices for Go Lambda functions

Adhere to the guidelines in the following list to use best coding practices when building your Lambda functions:


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4