Go 中的 Amazon Lambda 函数处理程序 - Amazon Lambda
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Go 中的 Amazon Lambda 函数处理程序

Lambda 函数处理程序是函数代码中处理事件的方法。当调用函数时,Lambda 运行处理程序方法。您的函数会一直运行,直到处理程序返回响应、退出或超时。

Go 中编写的 Lambda 函数被编写为 Go 可执行文件。在你的 Lambda 函数代码中,你需要包含 github.com/aws/ /lambda 包,它实现了 Go 的 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

  • import:您可以使用它来包含 Lambda 函数所需的库。在此实例中,它包括:

  • func HandleRequest (ctx context.Context,event *MyEvent)(*字符串,错误):这是你的 Lambda 处理程序的签名。它是 Lambda 函数的入口点,包含调用函数时执行的逻辑。此外,包含的参数表示以下含义:

    • ctx context.Context:为您的 Lambda 函数调用提供运行时信息。ctx 是您声明的变量,用于利用通过 Go 中的 Amazon Lambda上下文对象 提供的信息。

    • e@@ vent * MyEvent:这是一个指向event的名为的参数MyEvent。它表示 Lambda 函数的输入。

    • *string, error:处理程序返回两个值。第一个是指向包含 Lambda 函数结果的字符串的指针。第二个是错误类型,如果没有错误,则为 nil;如果出错,则包含标准错误信息。有关自定义错误处理的更多信息,请参阅Go 中的 Amazon Lambda 函数错误

    • return &message, nil:返回两个值。第一个是指向字符串消息的指针,它是使用输入事件中的 Name 字段构造的问候语。第二个值 nil 表示该函数没有遇到任何错误。

  • func main():这是运行您的 Lambda 函数代码的入口点。该项为必填项。

    通过在 func main(){} 代码括号之间添加 lambda.Start(HandleRequest),可以执行您的 Lambda 函数。按照 Go 语言标准,开括号即 { 必须直接置于 main 函数签名末尾。

命名

provided.al2 与 provided.al2023 运行时系统

对于使用 .zip 部署包中的 provided.al2provided.al2023 运行时系统的 Go 函数,包含函数代码的可执行文件必须命名为 bootstrap。如果使用 .zip 文件部署函数,bootstrap 文件必须位于 .zip 文件的根目录中。对于使用容器映像中的 provided.al2provided.al2023 运行时系统的 Go 函数,可执行文件可以使用任何名称。

处理程序可以使用任何名称。要在代码中引用处理程序值,可以使用 _HANDLER 环境变量。

go1.x 运行时系统

对于使用 go1.x 运行时系统的 Go 函数,可执行文件和处理程序可以共享任何名称。例如,如果您将处理程序的值设置为 Handler,Lambda 将在 Handler 可执行文件中调用该 main() 函数。

要在 Lambda 控制台中更改函数处理程序名称,请在 Runtime settings(运行时设置)窗格中,选择 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!" }

若要导出,事件结构中的字段名称必须大写。有关处理来自Amazon事件源的事件的更多信息,请参阅 aws-lambda-go/events。

有效处理程序签名

在 Go 中构建 Lambda 函数处理程序时,您有多个选项,但您必须遵守以下规则:

  • 处理程序必须为函数。

  • 处理程序可能需要 0 到 2 个参数。如果有两个参数,则第一个参数必须实现 context.Context

  • 处理程序可能返回 0 到 2 个参数。如果有一个返回值,则它必须实现 error。如果有两个返回值,则第二个值必须实现 error。有关实现错误处理信息的更多信息,请参阅Go 中的 Amazon Lambda 函数错误

下面列出了有效的处理程序签名。TInTOut 表示类型与 encoding/json 标准库兼容。有关更多信息,请参阅 func Unmarshal,以了解如何反序列化这些类型。

  • 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 函数,该函数在加载您的处理程序时执行。这在 Amazon Lambda 中行为方式相同,正如在标准 Go 程序中一样。您的 Lambda 函数的单个实例绝不会同时处理多个事件。

例 具有全局变量的 Go 函数
注意

此代码使用 Amazon SDK for Go V2。有关更多信息,请参阅 Amazon 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 := "examplebucket" 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) }