質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

解決済

1回答

3128閲覧

Lambda関数をローカルで実行する方法を教えてください

rapsody

総合スコア7

AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

1クリップ

投稿2021/05/07 23:28

編集2021/05/07 23:40

##解決したいこと
下記のコードをローカルで実行したいです。

Go

1package main 2 3import ( 4 "fmt" 5 6 "github.com/aws/aws-lambda-go/lambda" 7) 8 9type MyEvent struct { 10 Name string `json:"What is your name?"` 11 Age int `json:"How old are you?"` 12} 13 14type MyResponse struct { 15 Message string `json:"Answer:"` 16} 17 18func HandleLambdaEvent(event MyEvent) (MyResponse, error) { 19 return MyResponse{Message: fmt.Sprintf("%s is %d years old!", event.Name, event.Age)}, nil 20} 21 22func main() { 23 lambda.Start(HandleLambdaEvent) 24} 25

Go言語で書いたAWS Lambda関数をローカルで実行する方法を知りたいです。既にSAM(Serverless Application Model)を使用すればローカルでプログラムを実行できそうなことは調べております。が、SAMを使用しなくてもできるとシニアエンジニアの方に言われました。

ヒントとして、下記のlambda.start()を

go

1func main() { 2 lambda.Start(HandleLambdaEvent) 3}

go

1func main() { 2 ctx := context.Background() 3 hogehoge(ctx) 4}

にすることで、ローカルでも実行できると言われております。
なぜ、hogehogeに引数としてctxを入力する必要があるのか?
hogehogeに引数としてctxを入力することで、ローカルでも実行できるようになるのか?
がわかりません。

調べたら出てくるかと思い、質問せずに終わりましたが、そのとき質問をすればよかったと深く後悔しております。

調べたこと・理解していること

  • Lambda関数は、リクエストなどのイベントを処理するためのもの
  • main関数の中にあるLambda.start(ハンドラー)によってLambda関数が実行される
  • Contextに関して↓

Context は、APIのサーバーやクライアントを使うときに、コンテキストを提供してキャンセルや、タイムアウト、値を渡したり出来る仕組み。

Go の Context を学ぶ
とのことですが、理解できませんでした。

次に、この下記のサイトをみました。

環境と呼び出しリクエストに関するメタデータへのアクセス

Go の AWS Lambda context オブジェクト

要するにリクエストが処理されるときにメタデータが作成?されていて、それにアクセスできるという理解です。

背景

AWS Lambdaコンソールを開いて、Goの圧縮した実行ファイルをアップロードして、動作確認&テストをするのはデバッグができないし、手間がかかるからです。

環境

  • VsCode Version: 1.56.0
  • Mac M1
  • Delve Debugger Version: 1.6.0
  • Go version: go1.16.3 darwin/arm64
  • aws-cli/2.2.0 Python/3.9.4 Darwin/20.3.0 source/arm64 prompt/off

AWSやGoを使い始めたばかりであり、わからないことがたくさんあります。その上で一つずつ学び、何とか目的を実現したいと思っています。

指針を示していただくだけでもありがたいので、どうぞよろしくお願いいたします

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

go

1func main() { 2 ctx := context.Background() 3 hogehoge(ctx) 4}

にすることで、ローカルでも実行できると言われております。

"ローカルでも実行" という意味が、デプロイしたLambdaをローカルで動かしたいのか、ハンドラのロジックをローカルで動かしたいのか、にもよりますが、後者を仮定して回答します。

ます aws-lambda-go を用いてLambdaを実装するには Start などの関数を用いる必要があります。

そのため

go

1func main() { 2 ctx := context.Background() 3 hogehoge(ctx) 4}

のようにするとLambdaのエントリポイントとして意味をなさないため、不適切です。また Context はLambdaをローカルで実行することに対して無関係です。


ローカルで動かす方法

大きく2つの方法が考えられます。

1.ハンドラのロジックを別パッケージに分離する方法
2.環境変数 AWS_EXECUTION_ENV を見て判断する方法

1.ハンドラのロジックを別パッケージに分離する方法

ハンドラのロジックをローカルで動かしたいとき、ないしはハンドラの単体テストを実施したいときは、Lambdaの起動ポイントとハンドラのロジック部分を別のパッケージに分離する手法がよくあります。lambda.Startmain パッケージで実装し、ハンドラは app (など)のパッケージで実装する、ということです。以下が一例です。

  • ディレクトリ構成
. ├── cmd │   └── main.go ├── go.mod ├── go.sum ├── handle.go └── handle_test.go
  • handle.go

go

1package app 2 3import "fmt" 4 5type MyEvent struct { 6 Name string `json:"What is your name?"` 7 Age int `json:"How old are you?"` 8} 9 10type MyResponse struct { 11 Message string `json:"Answer:"` 12} 13 14func HandleLambdaEvent(event MyEvent) (MyResponse, error) { 15 return MyResponse{Message: fmt.Sprintf("%s is %d years old!", event.Name, event.Age)}, nil 16}
  • handle_test.go

go

1package app 2 3import ( 4 "reflect" 5 "testing" 6) 7 8func TestHandleLambdaEvent(t *testing.T) { 9 type args struct { 10 event MyEvent 11 } 12 tests := []struct { 13 name string 14 args args 15 want MyResponse 16 wantErr bool 17 }{ 18 { 19 name: "正常系", 20 args: args{event: MyEvent{Name: "Gopher", Age: 11}}, 21 want: MyResponse{ 22 Message: "Gopher is 11 years old!", 23 }, 24 wantErr: false, 25 }, 26 } 27 for _, tt := range tests { 28 t.Run(tt.name, func(t *testing.T) { 29 got, err := HandleLambdaEvent(tt.args.event) 30 if (err != nil) != tt.wantErr { 31 t.Errorf("HandleLambdaEvent() error = %v, wantErr %v", err, tt.wantErr) 32 return 33 } 34 if !reflect.DeepEqual(got, tt.want) { 35 t.Errorf("HandleLambdaEvent() got = %v, want %v", got, tt.want) 36 } 37 }) 38 } 39}
  • cmd/main.go

go

1package main 2 3import ( 4 "github.com/aws/aws-lambda-go/lambda" 5 app "github.com/d-tsuji/go-sandbox/teratail" 6) 7 8func main() { 9 lambda.Start(app.HandleLambdaEvent) 10}

上記のようにすると、ハンドラ (HandleLambdaEvent) をローカルでテストできるようになります。

2.環境変数 AWS_EXECUTION_ENV を見て判断する方法

もう一つの方法として AWS_EXECUTION_ENV を見て、AWS Lambda上で動いているかローカルで動いているか判断して分岐する方法があります。

AWS Lambdaとして動いている場合は AWS_EXECUTION_ENV のプレフィクスに AWS_Lambda_ が含まれます。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.html

そのため以下のようにして、ローカルの場合は直接ハンドラを動かすことができます。

go

1func main() { 2 if strings.HasPrefix(os.Getenv("AWS_EXECUTION_ENV"), "AWS_Lambda") { 3 lambda.Start(HandleLambdaEvent) 4 } else { 5 // AWS Lambda上で動いていない 6 _, err := HandleLambdaEvent(MyEvent{"Gopher", 11}) 7 if err != nil { 8 log.Fatal(err) 9 } 10 } 11}

投稿2021/05/08 00:29

d_tutuz

総合スコア730

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rapsody

2021/05/08 02:14

回答していただきありがとうございます! main()の中は、lambda.Start(app.HandleLambdaEvent) ではなく、 lambda.Start(app.TestHandleLambdaEvent) ではないでしょうか? Lambda.start()で、 HandleLambdaEventが呼ばれて、 HandleLambdaEventメソッドが実行されて、なぜ、TestHandleLambdaEventが実行されるのでしょうか? すいません、 理解力がなく申し訳ございません。
d_tutuz

2021/05/08 04:19

lambda.Start(app.HandleLambdaEvent) ですね。AWS LambdaとしてデプロイしてLambdaを実行したときは app.HandleLambdaEvent が呼び出されます。 ローカルでテストしたいときは go test -v などとして TestHandleLambdaEvent を実行することで、テストの中で HandleLambdaEvent を呼び出すことができる、ということです。TestHandleLambdaEvent はローカルでのテスト(go test を実行したとき)以外は TestHandleLambdaEvent は実行されません
rapsody

2021/05/08 07:02

ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問