AWSLambdaがGo言語に対応したのでDynamoDBと絡ませながらデモってみた

# はじめに

去年のRe:Inventで「来年の早い時期にLambdaがGoに対応するよ！」なんてアナウンスされた時は、来たかっ！という気持ちになりました。
首を長くして待っていたら、本日サポートしたと発表があったので早速試してみました。

## デモdemo

普段Node.jsを使ってLambda+DynamoDBの構成を組んでいるので、今回もDynamoDBを絡めてデモってみました。

公式が出している[記事](https://aws.amazon.com/jp/blogs/compute/announcing-go-support-for-aws-lambda/)を参考にしていただければいいのですが、
現時点でサポートしているバージョンは `1.x` です。
基本的なデプロイの流れは
1. Go書く
2. Linux用にビルドする
3. zipでアップロード
という流れになると思います。

## Go書く

基本形は下記のような感じです。

```go
package main

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

type Response struct {
    Message string `json:"message"`
    Ok      bool   `json:"ok"`
}

func Handler() (Response, error) {
    // 処理部分
}

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

`lambda.Start(Handler)` でLambdaの処理を実行します。
なんか少し違和感があるのは私だけでしょうか…
んで、 `Handler` の中に実際の処理を書いていく感じになります。

### DynamoDB(GetItem, PutItem, Query)

aws-sdk for goを使ってDynamoDBにリクエストを送っていきます。
上記のソースコードに追記したのが下記になります。

```go
package main

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/aws/aws-lambda-go/lambda"
	"fmt"
)

type Response struct {
	Message string `json:"message"`
	Ok      bool   `json:"ok"`
}

func Handler() (Response, error) {
    // session
    sess, err := session.NewSession()
    if err != nil {
        panic(err)
    }

    svc := dynamodb.New(sess)

    // GetItem
    getParams := &dynamodb.GetItemInput{
        TableName: aws.String("go-demo"),
        Key: map[string]*dynamodb.AttributeValue{
            "id": {
                S: aws.String("1"),
            },
        },
    }

    getItem, getErr := svc.GetItem(getParams)
    if getErr != nil {
        panic(getErr)
    }
    fmt.Println(getItem)

    // PutItem
    putParams := &dynamodb.PutItemInput{
        TableName: aws.String("go-demo"),
        Item: map[string]*dynamodb.AttributeValue{
            "id": {
                S: aws.String("2"),
            },
            "name": {
                S: aws.String("hoge"),
            },
        },
    }

    putItem, putErr := svc.PutItem(putParams)
    if putErr != nil {
        panic(putErr)
    }
    fmt.Println(putItem)

    // Query
    queryParams := &dynamodb.QueryInput{
        TableName: aws.String("go-demo"),
        KeyConditionExpression: aws.String("#ID=:id"),
        ExpressionAttributeNames: map[string]*string{
            "#ID": aws.String("id"),
        },
        ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
            ":id": {
                S: aws.String("1"),
            },
        },
    }

    queryItem, queryErr := svc.Query(queryParams)
    if queryErr != nil {
        panic(queryErr)
    }
    fmt.Println(queryItem)

    return Response{
        Message: fmt.Sprintln(getItem.Item),
        Ok:      true,
    }, nil
}

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

```

GetItemで返ってくるレスポンスはこんな感じ

```
{
  Item: {
    id: {
      S: "1"
    },
    name: {
      S: "test"
    }
  }
}
```

Queryで返ってくるレスポンスはこんな感じ

```
{
  Count: 1,
  Items: [{
      id: {
        S: "1"
      },
      name: {
        S: "test"
      }
    }],
  ScannedCount: 1
}
```

## ビルドして、zipに固める

```
$ go build -o main.go
$ zip deployment.zip main
```

linux用にビルドしないといけないので、macの方は下記を実行してからzipに固めてください。

```
$ GOOS=linux go build -o main
```

## Lambdaにデプロイする

Lambdaのコンソールから新しく関数を作成して、ランタイムを `Go 1.x` を選択します。
アタッチするロールには今回はDynamoDB関係の権限も忘れずに。
<img width="1525" alt="スクリーンショット 2018-01-16 15.05.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/2ed27a09-af6a-e198-497a-2d3004a1c946.png">

関数が作成されたら、先ほど作成したZipファイルをアップロードすれば完了です。
<img width="1458" alt="スクリーンショット 2018-01-16 15.06.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/9ee5dfda-0dd8-f9fa-a208-8fb2e5572cc8.png">

これでGoを使ってDynamoDBのデータを操作できるぞ！

# あとがき

正直Go言語はほとんど触ったことなかったので、ソースコードはきったねぇと思いますがご了承ください。
Node.jsの感覚で実装したら動いたって感じです…(汗)

Node.jsで実装していると「シングルスレッドじゃあしんどいな…」と感じている時もあったりします。
Go言語はNode.jsと違って並列処理に長けているので、ケースバイケースで「Node.jsよりもGoの方がよいんでは？」となりそうなので、今のうちにGo言語に慣れておかなければと実感しました。

ではまた！