AWS LambdaでGoを使う際に調べたこと

## はじめに

AWS LambdaでGoを使いたいなと思い、その際調べたことをまとめました。

## 参考にしたリンクとメモ

### 基本事項

#### [Go による Lambda 関数のビルド](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/go-programming-model.html)

- 公式ドキュメント
- Lambda関数コードにgithub.com/aws/aws-lambda-go/lambdaパッケージを含むことが必要
- func main(){}コードの括弧内に`lambda.Start(ハンドラ関数)`を追加すると、Lambda関数が実行される

```go:main.go
package main

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

func handler() {
    ...(略)...
}

func main() {
    lambda.Start(HandleLambdaEvent)
}
```

#### [新人が書いたGoのAWS Lambdaをレビューして学んだこと、困っていること](http://kdnakt.hatenablog.com/entry/2019/01/23/080000)

- **[ハンドラ関数とコアロジックを分離してテストを書く]** が参考になった

#### [ローカル環境でgoで書いた aws lambda用のコードを実行しちゃう](https://www.kaeruspoon.net/articles/1176)

- AWS SAMを用いていた
- Makefileはあった方が良さそうと思った


### Slackにメッセージを送る

#### [LambdaのGolangでSlackにメッセージを送る](https://techte.co/2018/01/28/lambda-go-slack/)

- **Lambdaの作成** を参考に、GoでSlackにメッセージを送る部分を実装した


<details><summary>main.go</summary><div>

```go:main.go
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/aws/aws-lambda-go/lambda"
	"github.com/suaaa7/go-lambda/pkg/slack"
)

// MyEvent has Text
type MyEvent struct {
	Text string
}

// HandleLambdaEvent returns error
func HandleLambdaEvent(ctx context.Context, event MyEvent) error {
	var slackURL = fmt.Sprintf(
		"https://hooks.slack.com/services/%s", os.Getenv("WEBHOOK_URL"))

	sl := slack.NewSlack(slackURL, event.Text, "AWS Lambda", "", "", "")
	err := sl.Send()
	if err != nil {
		return err
	}

	return nil
}

func main() {
	lambda.Start(HandleLambdaEvent)
}
```

</div></details>

<details><summary>pkg/slack/slack.go</summary><div>

```go:pkg/slack/slack.go
package slack

import (
	"encoding/json"
	"net/http"
	"net/url"
)

// Slack has Url and Params
type Slack struct {
	url    string
	params params
}

// params has 5 values
type params struct {
	Text      string `json:"text"`
	Username  string `json:"username"`
	IconEmoji string `json:"icon_emoji"`
	IconURL   string `json:"icon_url"`
	Channel   string `json:"channel"`
}

// NewSlack returns *slack
func NewSlack(url, text, username, iconEmoji, iconURL, channel string) *Slack {
	p := params{
		Text:      text,
		Username:  username,
		IconEmoji: iconEmoji,
		IconURL:   iconURL,
		Channel:   channel,
	}

	return &Slack{url: url, params: p}
}

// Send returns error
func (s *Slack) Send() error {
	params, err := json.Marshal(s.params)
	if err != nil {
		return err
	}

	resp, err := http.PostForm(
		s.url,
		url.Values{"payload": {string(params)}},
	)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	return nil
}

```

</div></details>

#### [Goのtimeパッケージのリファレンスタイム（2006年1月2日）は何の日？](https://qiita.com/ruiu/items/5936b4c3bd6eb487c182)

- SlackにLambda実行時間を出力する際に参考にした
- フォーマットの指定の仕方が`yyyyMMdd`とか`%Y-%m-%d`ではなく、特殊なルールがあって驚いた



### LambdaからS3へGet, Postする


#### [AWS SDK for Go API Reference](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/)

- 情報量が多すぎてしんどい

#### [Performing Basic Amazon S3 Bucket Operations](https://docs.aws.amazon.com/ja_jp/sdk-for-go/v1/developer-guide/s3-example-basic-bucket-operations.html)

- 基本的なものだけに絞られていて良かった

#### [SAM CLI + Golang でlambda s3 to s3を実現する](https://qiita.com/yoshihir/items/ba4b63a2967551a25f53)

- テストがしっかり書かれていて参考になった


### apexでデプロイする

#### [ApexでGoのLambdaを作成しようとしたら少しハマった](https://dev.classmethod.jp/cloud/aws/pitfall-of-apex-for-lambda-go/)

- apexでデプロイする際にとても参考になった


## その他参考にしたリンク

#### [SNSトピックへのメッセージをGoランタイムのLambdaでSlack通知する](https://k-masatany.hatenablog.com/entry/2018/02/16/170349)

#### [LambdaのGolangでS3を操作する](https://techte.co/2018/02/09/lambda-go-s3/)


#### [Lambda + Apex + Goでslackにメッセージを飛ばす](https://qiita.com/sion_cojp/items/cf203c9ff8473f934512)