0

查看 Go文档 https://docs.aws.amazon.com/lambda/latest/dg/golang-handler.html中官方AWS Lambda 函数处理程序中使用全局状态部分

建议在 ie 中初始化所有全局状态,func init() 即我们希望在多个 lambda 调用之间共享的任何包级别 vars 到这里。
我的理解是,每次 lambda 容器启动(即冷启动)都会进行一次初始化。

我的问题是,是否可以使用func main()代替func init(). 由于运行的副作用,
使用func init()基本上使我的处理程序函数 ( ) 不可单元测试。 将代码移动到似乎很容易解决这个问题。使用vs 有副作用吗func LambdaHandlerfunc init()
func init()func main()
func main()func init()

代码示例

使用 func init()

package main
 
import (
        "log"
        "github.com/aws/aws-lambda-go/lambda"
        "github.com/aws/aws-sdk-go/aws/session"
        "github.com/aws/aws-sdk-go/service/s3"
        "github.com/aws/aws-sdk-go/aws"
)
 
var invokeCount = 0
var myObjects []*s3.Object
func init() {
        svc := s3.New(session.New())
        input := &s3.ListObjectsV2Input{
                Bucket: aws.String("examplebucket"),
        }
        result, _ := svc.ListObjectsV2(input)
        myObjects = result.Contents
}
 
func LambdaHandler() (int, error) {
        invokeCount = invokeCount + 1
        log.Print(myObjects)
        return invokeCount, nil
}
 
func main() {
        lambda.Start(LambdaHandler)
}

对比

使用函数 main()

package main
 
import (
        "log"
        "github.com/aws/aws-lambda-go/lambda"
        "github.com/aws/aws-sdk-go/aws/session"
        "github.com/aws/aws-sdk-go/service/s3"
        "github.com/aws/aws-sdk-go/aws"
)
 
var invokeCount = 0
var myObjects []*s3.Object
 
func LambdaHandler() (int, error) {
        invokeCount = invokeCount + 1
        log.Print(myObjects)
        return invokeCount, nil
}
 
func main() {
        svc := s3.New(session.New())
        input := &s3.ListObjectsV2Input{
                Bucket: aws.String("examplebucket"),
        }
        result, _ := svc.ListObjectsV2(input)
        myObjects = result.Contents

        lambda.Start(LambdaHandler)
}
4

1 回答 1

6

我会提出以下建议(我们在很多 Go Lambda 中都成功地使用了它)。

main.go

[...]

func (h *handler) handleRequest(ctx context.Context) error {
    input := h.s3Client.ListObjectsV2Input{
        Bucket: aws.String("examplebucket"),
    }

    [...]
}

type handler struct {
    s3Client s3iface.S3API
}

// main is called only once, when the Lambda is initialised (started for the first time). Code in this function should
// primarily be used to create service clients, read environments variables, read configuration from disk etc.
func main() {
    h := handler{
        s3client: s3.New(session.New()),
    }

    lambda.Start(h.handleRequest)
}

main_test.go

type ListObjectsV2Mock struct {
    s3iface.S3API

    output *s3.ListObjectsV2Output
}

func TestHandleRequest(t *testing.T) {
    h := handler{
        s3Client: &ListObjectsV2Mock{
            output: &s3.ListObjectsV2Output{...},
        },
    }

    err := h.HandleRequest(context.TODO())
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
}

显然,缺少很多代码(导入、错误处理等),但这就是它的要点。

于 2021-06-03T16:35:03.000 回答