AWS Lambda with Go のハンドラ
AWS Lambda を Go で実装するとき、ハンドラを lambda.Start() に渡して実行することが多いと思います。1
lambda.Start()
が受け取るハンドラの型は interface{}
です。これは empty interface なのでどんな型でも入れることができますが、実際には守らないといけない条件があります。
package main import ( "fmt" "github.com/aws/aws-lambda-go/lambda" ) func myHandler() { fmt.Println("hello") } func main() { // ハンドラを lambda.Start() に渡す lambda.Start(myHandler) }
ハンドラのシグネチャ
AWS Lambda function handler in Go - AWS Lambda で説明されているように
lambda.Start()
に渡すハンドラは関数であり、以下のシグネチャである必要があります。
シグネチャを満たさない場合、Lambda 実行時にエラーが発生します。
func () func () error func (TIn) error func () (TOut, error) func (TIn) (TOut, error) func (context.Context) error func (context.Context, TIn) error func (context.Context) (TOut, error) func (context.Context, TIn) (TOut, error)
ハンドラの引数
シグネチャにも書いてあるように、ハンドラは引数 TIn
を受け取れます。
これにより CloudWatch event などから受け取ったデータをハンドラに渡すことが出来ます。
公式サンプルのハンドラ では
events.CloudWatchEvent
を受け取っています。
// CloudWatchEvent is the outer structure of an event sent via CloudWatch Events. // For examples of events that come via CloudWatch Events, see https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/EventTypes.html type CloudWatchEvent struct { Version string `json:"version"` ID string `json:"id"` DetailType string `json:"detail-type"` Source string `json:"source"` AccountID string `json:"account"` Time time.Time `json:"time"` Region string `json:"region"` Resources []string `json:"resources"` Detail json.RawMessage `json:"detail"` } func handler(ctx context.Context, event events.CloudWatchEvent) { fmt.Printf("Detail = %s\n", event.Detail) }
TIn
は json.Unmarshal() に対応している必要があります。
これは外部からの JSON データが []byte
から TIn
に json.Unmarshal()
され、ハンドラに渡されるためです。 2
先ほどの events.CloudWatchEvent
も JSON と構造体のフィールドを対応させる tag がついていて、 json.Unmarshal()
に対応しています。
外部からの JSON データがハンドラに渡されるまでの流れは以下のページが詳しいです。
https://www.mo4tech.com/aws-lambda-for-go.html
json のエンコード・デコードついては以下のページが詳しいです。
https://zenn.dev/hsaki/articles/go-convert-json-struct
ハンドラの戻り値
ハンドラは (error)
または (TOut, error)
の形で結果を返せます。
TOut
は TIn
とは逆に json.Marshal() に対応している必要があります。 3
公式サンプル では (events.APIGatewayProxyResponse, error)
で返しています。
// Handler is your Lambda function handler // It uses Amazon API Gateway request/responses provided by the aws-lambda-go/events package, // However you could use other event sources (S3, Kinesis etc), or JSON-decoded primitive types such as 'string'. func Handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { // stdout and stderr are sent to AWS CloudWatch Logs log.Printf("Processing Lambda request %s\n", request.RequestContext.RequestID) // If no name is provided in the HTTP request body, throw an error if len(request.Body) < 1 { return events.APIGatewayProxyResponse{}, ErrNameNotProvided } return events.APIGatewayProxyResponse{ Body: "Hello " + request.Body, StatusCode: 200, }, nil }
-
lambda.StartHandler() を使うと複雑な処理をするハンドラが書けるみたいです。こちらのページが詳しいです: https://zenn.dev/wim/articles/get_raw_input_data_by_go_lambda↩
-
https://github.com/aws/aws-lambda-go/blob/0462b0000e7468bdc8a9c456273c1551fab284aa/lambda/handler.go#L115↩
-
https://github.com/aws/aws-lambda-go/blob/0462b0000e7468bdc8a9c456273c1551fab284aa/lambda/handler.go#L24-L32↩