Go の Lambda 関数ハンドラーの定義 - AWS Lambda

Go の Lambda 関数ハンドラーの定義

Lambda 関数ハンドラーは、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。関数は、ハンドラーが応答を返すか、終了するか、タイムアウトするまで実行されます。

Go で書き込まれた Lambda 関数は、Go 実行可能ファイルとして作成されます。Lambda 関数コードでは、Go の Lambda プログラミングモデルを実装する github.com/aws/aws-lambda-go/lambda パッケージを含める必要があります。加えて、ハンドラー関数および main() 関数の実装が必要となります。

例 Go Lambda 関数
package main import ( "context" "fmt" "github.com/aws/aws-lambda-go/lambda" ) type MyEvent struct { Name string `json:"name"` } func HandleRequest(ctx context.Context, event *MyEvent) (*string, error) { if event == nil { return nil, fmt.Errorf("received nil event") } message := fmt.Sprintf("Hello %s!", event.Name) return &message, nil } func main() { lambda.Start(HandleRequest) }

次に示すのはこの関数の入力例です。

{ "name": "Jane" }

次の点に注意してください。

  • package main: Go では、func main() を含むパッケージは常に main と名付けられることが必要です。

  • インポート: これを使用して、Lambda 関数に必要なライブラリを含めます。この場合、次のものが含まれます。

  • func HandleRequest(ctx context.Context, event *MyEvent) (*string, error): これは Lambda ハンドラーの署名です。Lambda 関数のエントリポイントであり、関数が呼び出されたときに実行されるロジックが含まれています。また、次に示すパラメータも含まれます。

    • ctx context.Context: Lambda 関数呼び出しへのランタイム情報を提供します。ctx は、Go の AWS Lambda context オブジェクト を介して利用できる情報を活用する宣言を行う変数です。

    • event *MyEvent: これは MyEvent をポイントする event という名前のパラメータです。Lambda 関数への入力を表します。

    • *string, error: ハンドラーは 2 つの値を返します。1 つ目は、Lambda 関数の結果を含む文字列へのポインタです。2 つ目はエラータイプで、エラーがない場合は nil となり、何か問題が発生した場合は標準的なエラー情報 を含みます。

    • return &message, nil: 2 つの値を返します。1 つ目は文字列メッセージへのポインタです。これは、入力イベントの Name フィールドを使用して作成された挨拶文です。2 つ目の値は nil であり、関数でエラーが発生しなかったことを示します。

  • func main(): Lambda 関数コードが実行されるエントリポイント。これは必須です。

    func main(){} コードの括弧内に lambda.Start(HandleRequest) を追加すると、Lambda 関数が実行されます。Go 言語の規約に基づき、開き中括弧 { は main 関数シグネチャの直後に置く必要があります。

命名

provided.al2 および provided.al2023 ランタイム

.zip デプロイパッケージで provided.al2 または provided.al2023 ランタイムを使用する Go 関数の場合、関数コードを含む実行ファイルの名前は bootstrap である必要があります。.zip ファイルを使用して関数をデプロイする場合、bootstrap ファイルは .zip ファイルのルートにある必要があります。コンテナイメージprovided.al2 または provided.al2023 ランタイムを使用する Go 関数の場合、実行ファイルには任意の名前を使用できます。

ハンドラーには任意の名前を使用できます。コード内でハンドラー値を参照するには、_HANDLER 環境変数を使用できます。

go1.x ランタイム

go1.x ランタイムを使用する Go 関数の場合、実行ファイルとハンドラーは任意の名前を共有できます。例えば、ハンドラーの値を Handler に設定すると、Lambda はHandler 実行可能ファイル内の main() 関数を呼び出します。

Lambda コンソールの関数ハンドラー名を変更するには、ランタイム設定ペインで、[Edit] (編集) を選択します。

構造化されたタイプを使用した Lambda 関数ハンドラー

上記の例では、入力タイプは単純な文字列でした。ただし、構造化されたイベントを関数ハンドラーに渡すこともできます。

package main import ( "fmt" "github.com/aws/aws-lambda-go/lambda" ) type MyEvent struct { Name string `json:"What is your name?"` Age int `json:"How old are you?"` } type MyResponse struct { Message string `json:"Answer"` } func HandleLambdaEvent(event *MyEvent) (*MyResponse, error) { if event == nil { return nil, fmt.Errorf("received nil event") } return &MyResponse{Message: fmt.Sprintf("%s is %d years old!", event.Name, event.Age)}, nil } func main() { lambda.Start(HandleLambdaEvent) }

次に示すのはこの関数の入力例です。

{ "What is your name?": "Jim", "How old are you?": 33 }

レスポンスは次のようになります。

{ "Answer": "Jim is 33 years old!" }

エクスポートするには、イベント構造体のフィールド名が大文字である必要があります。AWS イベントソースでイベントを処理するための詳細は、「aws-lambda-go/events」を参照してください。

有効なハンドラー署名

Go で Lambda 関数ハンドラーを構築するには複数の方法がありますが、次のルールに従う必要があります。

  • ハンドラーは関数である必要があります。

  • ハンドラーは 0 から 2 までの引数を取る場合があります。2 つの引数がある場合は、最初の引数が context.Context を実装する必要があります。

  • ハンドラーは 0 から 2 までの引数を返す場合があります。単一の戻り値がある場合は、この値が error を実装する必要があります。2 つの戻り値がある場合には、2 番目の値が error を実装している必要があります。

次のリストは、有効なハンドラー署名の一覧です。 TInTOut は、 encoding/json 標準ライブラリと互換性のあるタイプを表しています。詳細については、「func アンマーシャリング」でこれらのタイプが逆シリアル化する方法を参照してください。

  • 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)

グローバルな状態を使用する

Lambda 関数のハンドラーコードとは別のグローバルな変数を宣言して変更することができます。さらに、ハンドラーがロードされている場合に実行される init 関数をハンドラーが宣言することがあります。これは、AWS Lambda でも標準の Go プログラムと同じように作動します。Lambda 関数の単一のインスタンスが、同時に複数のイベントを処理することはありません。

例 グローバル変数を使用する Go 関数
注記

このコードは AWS SDK for Go V2 を使用します。詳細については、「Getting Started with the AWS SDK for Go V2」を参照してください。

package main import ( "context" "github.com/aws/aws-lambda-go/lambda" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3/types" "log" ) var invokeCount int var myObjects []types.Object func init() { // Load the SDK configuration cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { log.Fatalf("Unable to load SDK config: %v", err) } // Initialize an S3 client svc := s3.NewFromConfig(cfg) // Define the bucket name as a variable so we can take its address bucketName := "DOC-EXAMPLE-BUCKET" input := &s3.ListObjectsV2Input{ Bucket: &bucketName, } // List objects in the bucket result, err := svc.ListObjectsV2(context.TODO(), input) if err != nil { log.Fatalf("Failed to list objects: %v", err) } myObjects = result.Contents } func LambdaHandler(ctx context.Context) (int, error) { invokeCount++ for i, obj := range myObjects { log.Printf("object[%d] size: %d key: %s", i, obj.Size, *obj.Key) } return invokeCount, nil } func main() { lambda.Start(LambdaHandler) }