drpogkqqi536984960 2019-09-10 14:07
浏览 82
已采纳

在Go中为AWS Lambda指定多个事件处理程序

Typically, a AWS Lambda event handler code in Go (using Serverless Framework) is coded as:

package main

import (
  "fmt"
  "context"
  "github.com/aws/aws-lambda-go/lambda"
)

type MyEvent struct {
  Name string `json:"name"`
}

func HandleRequest(ctx context.Context, name MyEvent) (string, error) {
  return fmt.Sprintf("Hello %s!", name.Name ), nil
}

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

The serverless.yml file then contains a section like:

  skeleton-go-get:
    name: skeleton-go-get
    runtime: go1.x
    handler: go-handler  # <- This specifies a file, not a function.
    events:
      - http:
          path: skeleton/go
          method: get

That ^ creates one request handler... but now I want my one Go script / program to contain the event handlers for both HTTP GET and POST requests, and not use one Go program file per serverless function.

Exactly this is possible in languages like Node.js, Ruby, Python, with the serverless.yml specifying which function in the handler file is to be used for which serverless function. For example (for Python functions):

[...]
functions:
  skeleton-python-get:
    name: skeleton-python-get
    handler: python-handler.handle_get  # <- Specifies the HTTP GET handler.
    events:
      - http:
          path: skeleton/python
          method: get
  skeleton-python-post:
    name: skeleton-python-post
    handler: python-handler.handle_post  # <- Specifies the HTTP POST handler.
    events:
      - http:
          path: skeleton/python
          method: post

I cannot get this same trick to work for Go. I tried to include the proper request in main() but to no avail:

func HandleGetRequest(ctx context.Context, name MyEvent) (string, error) {
  return fmt.Sprintf("Hello %s!", name.Name ), nil
}

func HandlePostRequest(ctx context.Context, name MyEvent) (string, error) {
  return fmt.Sprintf("Hello %s!", name.Name ), nil
}

func main() {
  lambda.Start(HandleGetRequest)
  lambda.Start(HandlePostRequest)  // <- Attempt to add another handler.
}

And specifying multiple event handler functions in the serverless.yml file for the Go handlers also doesn't work: the function isn't a valid part of the handler declaration.

  skeleton-go-get:
    name: skeleton-go-get
    runtime: go1.x
    handler: go-handler.HandleGet  # <- Attempt to specify a function.
    events:
      - http:
          path: skeleton/go
          method: get

  skeleton-go-post:
    name: skeleton-go-post
    runtime: go1.x
    handler: go-handler.HandlePost  # <- Attempt to specify a function.
    events:
      - http:
          path: skeleton/go
          method: post

Q: How can I include more than one AWS Lambda event handler in one Go program (using Serverless Framework)?

  • 写回答

1条回答 默认 最新

  • dongsimu4422 2019-09-10 15:16
    关注

    You can use the same function (and handler) for your get and your post:

    skeleton-go:
        name: skeleton-go
        runtime: go1.x
        handler: go-handler
        events:
          - http:
              path: skeleton/go
              method: get
          - http:
              path: skeleton/go
              method: post
    

    Use Go's built-in HTTP router or use a third-party one, such as Gorilla Mux or Chi as shown in the example code below (because that's what I had handy). In essence, you're building a Go HTTP server, but in Lambda. So, follow the details for setting up a Go web server, and take a look at AWS's API Gateway Proxy.

    package main
    
    import (
        "context"
        "net/http"
    
        "github.com/aws/aws-lambda-go/events"
        "github.com/aws/aws-lambda-go/lambda"
    
        "github.com/go-chi/chi"
        chiproxy "github.com/awslabs/aws-lambda-go-api-proxy/chi"
    )
    
    var adapter *chiproxy.ChiLambda
    
    func GetSkeleton(w http.ResponseWriter, r *http.Request) {
        ...
    }
    
    func PostSkeletonToMom(w http.ResponseWriter, r *http.Request) {
        ...
    }
    
    func init() {
        r := chi.NewRouter()
    
        r.Get("/skeleton/go", GetSkeleton)
        r.Post("/skeleton/go", PostSkeletonToMom)
    
        adapter = chiproxy.New(r)
    }
    
    func lambdaHandler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
        c, err := adapter.ProxyWithContext(ctx, req)
    
        return c, err
    }
    
    func main() {
        lambda.Start(lambdaHandler)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 Matlab打开默认名称带有/的光谱数据
  • ¥50 easyExcel模板 动态单元格合并列
  • ¥15 res.rows如何取值使用
  • ¥15 在odoo17开发环境中,怎么实现库存管理系统,或独立模块设计与AGV小车对接?开发方面应如何设计和开发?请详细解释MES或WMS在与AGV小车对接时需完成的设计和开发
  • ¥15 CSP算法实现EEG特征提取,哪一步错了?
  • ¥15 游戏盾如何溯源服务器真实ip?需要30个字。后面的字是凑数的
  • ¥15 vue3前端取消收藏的不会引用collectId
  • ¥15 delphi7 HMAC_SHA256方式加密
  • ¥15 关于#qt#的问题:我想实现qcustomplot完成坐标轴
  • ¥15 下列c语言代码为何输出了多余的空格