Go言語でDynamoDB接続を試みたときの備忘録

# 前提

最近、Go言語を触り始めた。

GoからDynamoDBに接続するにあたって、 `aws-sdk-go/aws/service/dynamodb` を使おうとし、ドキュメントを読んでたら結構難しそうだったので、 `guregu/dynamo` を使うことにした。

また、DynamoDBも触ったことがなかった。

ゴールは、GoでDynamoDBに読み書きすること！

# DynamoDBの設定

まず、AWSコンソール画面からDynamoDBのテーブルを作ります。

![スクリーンショット 2017-06-17 16.47.12.png](https://qiita-image-store.s3.amazonaws.com/0/88357/1b2161fa-7ca5-5ef5-65dd-6752b0289c99.png)

上記の画面で、「テーブル名」を `Test` とします。

「プライマリーキー」を `user_id` とします。型は「数値」にします。

他のattributeにかんしては、時間に関する値を想定してますが、実際にGoからItemをPUTするときに足されるので、定義する必要はありません。（そもそも登録もできない。）

（キャメルケースがいいのか、パスカルケースがいいのか等の命名規則もあるかと思いますが、一旦これでいきます。）

これでAWS側の用意は出来ました。

あと、もう一つ大事なこととして
IAMで、DynamoDBにアクセスできる権限をもったユーザーを作成し、

- アクセスキー
- シークレットキー

を入手しましょう。


# Go言語をかく！

user_dynamo.goという名前でファイルを作成します。

## 必要なモジュール

以下のリアブラリをimportします。

```go:user_dynamo.go
import (
  "fmt"
  "time"
  "github.com/aws/aws-sdk-go/aws"
  "github.com/aws/aws-sdk-go/aws/session"
  "github.com/aws/aws-sdk-go/aws/credentials"
  "github.com/guregu/dynamo"
)
```

|ライブラリ名|説明|
|---|---|
|fmt|標準出力に使う。|
|time|現在時刻を取得するのに使う。|
|github.com/aws/aws-sdk-go/aws|configに関するオブジェクト作成につかう|
|github.com/aws/aws-sdk-go/aws/session|sessionに関するオブジェクト作成につかう|
|github.com/aws/aws-sdk-go/aws/credentials|awsへのアクセス情報に関するオブジェクト作成につかう|
|github.com/guregu/dynamo|github.com/aws/aws-sdk-go/aws/service/dynamodbに対する操作を便利にしてくれるライブラリ|

## DynamoDBのスキーマ定義

この言い回しが正しいかわかりませんが、DynamoDBのUserテーブルに登録する予定の項目を構造体として定義します。

```go:user_dynamo.go
type User struct {
  UserId int `dynamo:"user_id"`
  CreatedTime time.Time `dynamo:"created_time"`
}
```

`int` や `time.Time` のあとのバッククウォートで囲まれた部分はGoで「タグ情報」と呼ばれるものになります。

## DynamoDBのUserテーブルにアクセス

```go:user_dynamo.go
func main(){
  c := credentials.NewStaticCredentials("<アクセスキー>", "<シークレットキー>", "") // 最後の引数は[セッショントークン]

  db := dynamo.New(session.New(), &aws.Config{
      Credentials: c,
      Region: aws.String("<region名>"), // "ap-northeast-1"等
  })
  table := db.Table("Test")

 // 続く
}
```

のように書きます。

## データをPUTする

```go:user_dynamo.go
func main(){
  // 続き

  u := User{UserId: 3, CreatedTime: time.Now().UTC()}
  fmt.Println(u)
  
  if err := table.Put(u).Run(); err != nil {
    fmt.Println("err")
    panic(err.Error())
  }
```


上記をまとめると

```go:user_dynamo.go
package main

import (
  "fmt"
  "time"
  "github.com/aws/aws-sdk-go/aws"
  "github.com/aws/aws-sdk-go/aws/session"
  "github.com/aws/aws-sdk-go/aws/credentials"
  "github.com/guregu/dynamo"
)


type User struct {
  UseId int `dynamo:"use_id"`
  CreatedTime time.Time `dynamo:"created_time"`
}


func main(){
  cred := credentials.NewStaticCredentials("<アクセスキー>", "<シークレットキー>", "") // 最後の引数は[セッショントークン]

  db := dynamo.New(session.New(), &aws.Config{
      Credentials: cred,
      Region: aws.String("<region名>"), // "ap-northeast-1"等
  })

  table := db.Table("User")

  u := User{UserId: 100, CreatedTime: time.Now().UTC()}
  fmt.Println(u)
  
  if err := table.Put(u).Run(); err != nil {
    fmt.Println("err")
    panic(err.Error())
  }
```

それではterminalから

```
$ go run user_dynamo.go
```

とうってみてください。DynamoDBに

|user_id|created_time|
|---|---|
|100|2017-06-02T09:25:56.000147134Z|

と登録されたかと思います。これで、DynamoDBへのデータ登録は完了です。


## データの読み取り

DynamoDBより

「user_idが100のデータ全て」

データを読み取る場合は以下のようになります。

```go:user_dynamo.go
func main(){
  // 続き
  var users []User
  err := table.Get("user_id", 100).All(&users)
  if err != nil {
    fmt.Println("err")
    panic(err.Error())
  }

  fmt.Println(users) // [{100 2017-06-02T09:25:56.000147134 +0000 UTC}]と出力される。

  for i, _ := range users {
    fmt.Println(users[i]) // {100 2017-06-02T09:25:56.000147134 +0000 UTC}
  }
}
```

また全データを取得したい場合は

```go:
err := table.Get("user_id", 1).All(&users)
```

というところを

```go:
err := table.Scan().All(&users)
```

とすれば大丈夫です。

さらに `created_time` によって、絞りたい場合は以下のようにすれば大丈夫です。

```
err := table.Get("user_id", 1).Filter("created_time >= ?", "2017-06-01 00:00:00").All(&users)
```

## 注意点

DynamoDBでは、プライマリーキーは、DBで一つしか存在できないので、本コードでは書き込みをするたびに書き換わります。


## 参考にしたサイト

http://www.geocities.jp/m_hiroi/golang/abcgo07.html
https://github.com/guregu/dynamo
http://qiita.com/guregu/items/2e9ac305791935b86f5d
https://developers.eure.jp/tech/aws-sdk-go-tutorial-sqs-dynamodb/