Go言語でAWSのサービスを使ってみる ~SQS・DynamoDBを試す~

gopher_aws-sqs-dynamodb
gopher_aws-sqs-dynamodb

はじめに

aws-sdk-go

import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/[サービス名]"
)func main(){
    // (1) セッションの作成(認証はここで行う)
    sess, err := session.NewSession()
    if err != nil {
        panic(err)
    }// サービス用クライアントの初期化(セッションを渡す)
    svc := [サービス名].New(sess)// APIのパラメータには API名+Input という構造体を使う
    params := [サービス名].GetHogeInput{
        Param1: aws.Int64(1),       // (2) パラメータをポインタとして渡す
        Param2: aws.String("hoge"), // (2) パラメータをポインタとして渡す
    }// APIの結果のレスポンスとエラーを受け取る
    resp, err := svc.GetHoge(params)}(※ 簡単な例示のためカジュアルにpanicしてたりエラーハンドリングが適切じゃなかったりします。実コードでは使わないようにしてください。)(1) ではセッションと呼ばれるオブジェクトを作成しています。
次の項目で詳しく説明します。(2) では GetHogeInput{} というパラメータ構造体を作っており、
そのパラメータは全てポインタとして渡しています。
aws.Int64()aws.String() は単に値のポインタを返却するだけの関数なので、
この関数を使わずに &value のような形でポインタを指定しても大丈夫です。session.Sessionの作成セッションの中には認証設定(クレデンシャル情報)やリクエストハンドラが含まれていて、
こいつを各サービスのコンストラクタに渡し、各サービス用のクライアントを作成します。
上の例では session.NewSession() の引数は空ですが、引数に "github.com/aws/aws-sdk-go/aws"*aws.Config{} を渡すことで、各種設定をすることができます。
(引数は可変で複数の *aws.Config{} を使うことができますが、後側の有効な設定でどんどん上書きされていくようです。空のNewSession// 空の引数でセッションを作成
sess, err := session.NewSession()この例のように *aws.Config{} を一切使わずにセッションを作成すると、以下のような挙動になります。
他のAWSのSDKと同様、使える環境変数は以下の通りです。環境変数  項目  優先  備考  AWS_ACCESS_KEY_ID  アクセスキーID  ○    AWS_ACCESS_KEY  アクセスキーID  ×    AWS_SECRET_ACCESS_KEY  シークレットアクセスキー  ○    AWS_SECRET_KEY  シークレットアクセスキー  ×    AWS_SESSION_TOKEN  セッショントークン  -    AWS_REGION  リージョン  ○    AWS_DEFAULT_REGION  リージョン  ×  AWS_SDK_LOAD_CONFIG が有効のときのみ  AWS_PROFILE  プロファイル  ○    AWS_DEFAULT_PROFILE  プロファイル  ×  AWS_SDK_LOAD_CONFIG が有効のときのみ  AWS_SHARED_CREDENTIALS_FILE  Shared credentialファイルのパス  -  デフォルトは $HOME/.aws/credentials  AWS_CONFIG_FILE  configファイルのパス  -  AWS_SDK_LOAD_CONFIG が有効のときのみ, デフォルトは $HOME/.aws/config  AWS_SDK_LOAD_CONFIG  -  -  有効にするには 1true っぽい文字列を使う異なる「環境変数」にて同一の「項目」が設定されている場合は、
「優先」がのものが優先されます。指定値でのNewSessionアクセスキーIDやシークレットアクセスキーをコード中で直接指定したい場合は、
以下のように credentials.NewStaticCredentials()*aws.Config{} を使います。import (
    "github.com/aws/aws-sdk-go/aws/credentials"
)func main() {
    // クレデンシャルの作成
    cred := credentials.NewStaticCredentials("[アクセスキーID]", "[シークレットアクセスキー]", "") // 最後の引数は[セッショントークン]// クレデンシャルとリージョンをセットしたコンフィグの作成
    region := "ap-northeast-1"
    conf := &aws.Config{
        Credentials: cred,
        Region:      &region,
    }// セッションの作成
    sess, err := session.NewSession(conf)
    if err != nil {
        panic(err)
    }
}サービスエンドポイントの指定通常は指定したサービス名やリージョンによって自動的にエンドポイントURLが決まりますが、
これを任意のURLを使うように指定することができます。import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
)func main() {
    // エンドポイントをセットしたコンフィグの作成
    ep := "http://localhost:8080"
    conf := &aws.Config{
        Endpoint:      &ep,
    }// セッションの作成
    sess, err := session.NewSession(conf)
    if err != nil {
        panic(err)
    }
}こうすると、テスト時にDynamoDBLocaliain/fake_sqsといったダミーのサービスを使うことができて便利です。クレデンシャルの優先順位NewSession を使用した場合の優先順位は
となっているようです。もし特定の方法を使いたい場合は以下の関数の戻り値を、aws.Config{}.Credentials へセットすることで指定できます。
各サービスの使い方ここからは各AWSサービスの説明をしていきます。SQSまずはSQSから使ってみます。SQSクライアントは以下のようにして作成します。import (
    "github.com/aws/aws-sdk-go/service/sqs"
)// (中略)svc := sqs.New(sess) // `sess`はセッションこのクライアントの各メソッドに対して専用のパラメータ引数を渡すことでSQSの操作を行うことが出来ます。
ここからは、
を試していきます。SQS キューの作成(CreateQueue)キューの作成は以下のようにして行います。import (
    "github.com/aws/aws-sdk-go/service/sqs"
)// (中略)func createQueue() {
    // SQSクライアントの作成
    svc := sqs.New(sess)// パラメータ
    queueName := "キュー名"
    params := &sqs.CreateQueueInput{
        QueueName: &queueName,
    }// CreateQueueの実行
    resp, err := svc.CreateQueue(params)
    if err != nil {
        panic(err)
    }// リクエスト成功時、*resp.QueueUrl には SQSキューのURLが入ります
}svc.CreateQueue() のレスポンスのフィールドにはキューのURLが格納されています。
(不要であればレスポンス自体を _ に入れて捨ててしまいましょう。)SQS キューの取得(GetQueueUrl)キューURLの取得は以下のようにして行います。import (
    "github.com/aws/aws-sdk-go/service/sqs"
)// (中略)func getQueueUrl() {
    // SQSクライアントの作成
    svc := sqs.New(sess)// パラメータ
    queueName := "キュー名"
    params := &sqs.GetQueueUrlInput{
        QueueName: &queueName,
    }// GetQueueUrlの実行
    resp, err := svc.GetQueueUrl(params)
    if err != nil {
        panic(err)
    }// リクエスト成功時、*resp.QueueUrl には SQSキューのURLが入ります
}取得した QueueUrl はキューの削除やメッセージ操作で使用します。SQS キューの削除(DeleteQueue)キューの削除は以下のようにして行います。import (
    "github.com/aws/aws-sdk-go/service/sqs"
)// (中略)func deleteQueue() {
    // SQSクライアントの作成
    svc := sqs.New(sess)// パラメータ
    queueURL := "[キューURL]" // GetQueueUrl等で取得したキューのURLを入れる
    params := &sqs.DeleteQueueInput{
        QueueUrl: &queueURL,
    }// DeleteQueueの実行
    _, err := svc.DeleteQueue(params)
    if err != nil {
        panic(err)
    }// レスポンスには重要な内容はないため捨てています
}SQS メッセージの送信(SendMessage)メッセージの送信は以下のようにして行います。import (
    "github.com/aws/aws-sdk-go/service/sqs"
)// (中略)func sendMessage() {
    // SQSクライアントの作成
    svc := sqs.New(sess)// パラメータ
    queueURL := "" // GetQueueUrl等で取得したキューのURLを入れる
    body := `メッセージ内容`params := &sqs.SendMessageInput{
        QueueUrl:    &queueURL,
        MessageBody: &body,
        // MessageAttributes: map[string]*sqs.MessageAttributeValue{} // メタ情報用のパラメータ
    }// SendMessageの実行
    resp, err := svc.SendMessage(params)
    if err != nil {
        panic(err)
    }
}レスポンスにはMessageIdに加え、MessageBodyやMessageAttributesの内容をMD5化した文字列が含まれており、
正常に送信されたかどうか検証ができるようです。SQS メッセージの受信(ReceiveMessage)メッセージの受信は以下のようにして行います。import (
    "github.com/aws/aws-sdk-go/service/sqs"
)// (中略)func receiveMessage() {
    // SQSクライアントの作成
    svc := sqs.New(sess)// パラメータ
    queueURL := "" // GetQueueUrl等で取得したキューのURLを入れる
    max := 1
    wait := 10params := &sqs.ReceiveMessageInput{
        QueueUrl:    &queueURL,
        MaxNumberOfMessages: &max, // メッセージ最大受信数
        WaitTimeSeconds: &wait,    // ポーリング時間(秒)
    }// ReceiveMessageの実行
    resp, err := svc.ReceiveMessage(params)
    if err != nil {
        panic(err)
    }// resp.Messages に受信したメッセージリストが格納されます
    // *resp.Messages[i].Body に受信したメッセージ内容が格納されています
}送信に比べて、指定できるパラメータが増えていますね。MaxNumberOfMessages に指定した数値は、resp.Messages の中に入るメッセージ数の最大値になります。
例えば 10 を指定した場合は 0〜10件のメッセージが入る可能性があります。WaitTimeSeconds を設定するとロングポーリングを行うことができます。
指定した秒数だけポーリングし、メッセージの受信を待機することができます。なお、ここで受信したメッセージは削除時にも必要となります。SQS メッセージの削除(DeleteMessage)メッセージの削除は以下のようにして行います。(そろそろコピペして打つのも疲れてきました...)func deleteMessage() {
    // SQSクライアントの作成
    svc := sqs.New(sess)// パラメータ
    queueURL := "[キューURL]" // GetQueueUrl等で取得したキューのURLを入れる
    receiptHandle := "[ReceiptHandle]" // GetMessageで受信したメッセージ内の *resp.Messages[i].ReceiptHandle を入れるparams := &sqs.DeleteMessageInput{
        QueueUrl:    &queueURL,
        ReceiptHandle: &receiptHandle,
    }// DeleteMessageの実行
    _, err := svc.DeleteMessage(params)
    if err != nil {
        panic(err)
    }// レスポンスには重要な内容はないため捨てています
}メッセージの削除には、削除したいメッセージのReceiptHandleを含める必要があります。
GetMessageで受信したメッセージのReceiptHandleを使いましょう。SQSのその他のアクションこの他にもキュー一覧のListQueuesや溜まったキューのパージを行うPurgeQueue、
複数のメッセージの送信や削除を行う SendMessageBatchDeleteMessageBatch といったAPIがあります。詳しくは公式のドキュメントを参照してください。DynamoDBDynamoDBクライアントは以下のようにして作成します。import (
    "github.com/aws/aws-sdk-go/aws/service/dynamodb"
)// (中略)svc := dynamodb.New(sess) // `sess`はセッションSQSの場合とほぼ同じですね。このクライアントの各メソッドに対して専用のパラメータ引数を渡すことでDynamoDBの操作を行うことが出来ます。ここからは、
を試していきます。DynamoDB テーブルの作成(CreateTable)テーブルの作成は以下のようにして行います。(!!)
一時変数が多くなりそうだったので、ポインタ変換関数 aws.String()aws.Int64() を使ってます。import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/service/dynamodb"
)func main() {
    // DynamoDBクライアントの作成
    svc := dynamodb.New(sess)// パラメータ
    params := &dynamodb.CreateTableInput{
        AttributeDefinitions: []*dynamodb.AttributeDefinition{
            {
                AttributeName: aws.String("user_id"), // フィールド名
                AttributeType: aws.String("N"),       // フィールド型 N=number, S=string, B=bool で型を指定
            },
        },
        KeySchema: []*dynamodb.KeySchemaElement{
            {
                AttributeName: aws.String("user_id"), // フィールド名
                KeyType:       aws.String("HASH"),    // HASH=ハッシュキー, RANGE=レンジキー
            },
        },
        ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
            ReadCapacityUnits:  aws.Int64(1), // 読み込みスループット
            WriteCapacityUnits: aws.Int64(1), // 書き込みスループット
        },
        TableName:              aws.String("user_table"), // テーブル名
        // GlobalSecondaryIndexes: []*dynamodb.GlobalSecondaryIndex{}, // GSIの設定
        // LocalSecondaryIndexes:  []*dynamodb.LocalSecondaryIndex{}, // LSIの設定
    }// CreateTableの実行
    resp, err := svc.CreateTable(params)
    if err != nil {
        panic(err)
    }// resp.TableDescription の中にテーブル定義情報が入っています
}なんだかいきなり複雑になりましたね。DynamoDBを使ったことがある人にはお馴染みのパラメータかと思いますが、
ここにLocalSecondaryIndexGlobalSecondaryIndexが加わってくると、かなりラビリンスな状態になります。DynamoDB テーブルの情報取得(DescribeTable)テーブルの情報取得は以下のようにして行います。import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/service/dynamodb"
)func main() {
    // DynamoDBクライアントの作成
    svc := dynamodb.New(sess)// パラメータ
    params := &dynamodb.DescribeTableInput{
        TableName: aws.String("user_table"), // テーブル名
    }// DescribeTableの実行
    resp, err := svc.DescribeTable(params)
    if err != nil {
        panic(err)
    }// resp.Table の中にテーブル定義情報が入っています
}テーブル作成に比べると断然、簡単ですね。DynamoDB 項目のPUT(PutItem)項目ってなんやねんかと思うかもしれませんが、
RDBでいうところの行、ドキュメント指向KVSでいうところのドキュメントのことです。import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/service/dynamodb"
)func main() {
    // DynamoDBクライアントの作成
    svc := dynamodb.New(sess)// パラメータ
    params := &dynamodb.PutItemInput{
        TableName: aws.String("user_table"),       // テーブル名
        Item: map[string]*dynamodb.AttributeValue{ // 項目のデータ
            "user_id": {
                N: aws.String("100"),
            },
            "name": {
                S: aws.String("hoge"),
            },
        },
    }// PutItemの実行
    resp, err := svc.PutItem(params)
    if err != nil {
        panic(err)
    }
}作成に比べれば良心的ですね。Item にはキー名と値を入れます。値は dynamodb.AttributeValue{} を使います。
型に合わせて値を入れるフィールドが変わります。
例えば上の例のように、NumberならN、StringならSとなります。DynamoDB 項目の取得(GetItem)項目の取得には以下のようになります。import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/service/dynamodb"
)func main() {
    // DynamoDBクライアントの作成
    svc := dynamodb.New(sess)// パラメータ
    params := &dynamodb.GetItemInput{
        TableName: aws.String("user_table"),       // テーブル名
        Key: map[string]*dynamodb.AttributeValue{ // 項目のデータ
            "user_id": {
                N: aws.String("100"),
            },
        },
    }// GetItemの実行
    resp, err := svc.GetItem(params)
    if err != nil {
        panic(err)
    }// resp.Item の中に項目データが入っています
}使い方はPutとほぼ一緒ですね。Key にはインデックスのキーを指定します。
レンジキーが存在する場合はKeyのmap内に2つのデータが入ります。resp.Itemmap[string]*dynamodb.AttributeValue となっていて、
resp.Item["user_id"].N, resp.Item["name"].S のような形で値を取り出します。DynamoDBのその他のアクションここまででDynamoDBの実力(と辛さ)の10%も引き出せてないわけですが、
項目の一括取得を行うScanQuery、項目の削除を行うDeleteItemInputといったAPIがあります。詳しくは公式のドキュメントを参照してください。ラッパーライブラリ aws-sdk-go-wrapperDynamoDBを使っていると、N やら S やら B、さらには M といったフィールドに格納されたポインタをいじることになりますが、
我々人類にはまだ早いんじゃないかと思います。そんな時代の混乱を解決するためにラッパーライブラリを作っているので、ついでにここで宣伝させていただきます。(本題)evalphobia/aws-sdk-go-wrapper今のところは、S3やSQS、SNSにDynamoDBといったサービスに対応しています。コンフィグ公式のSDKの場合はセッションを作成し、サービス用クライアントに渡して作成しますが、
ラッパーでも同様にまずはコンフィグを作成しクライアントを作成します。簡単な例は以下のようになります。import (
    "github.com/evalphobia/aws-sdk-go-wrapper/config"
    "github.com/evalphobia/aws-sdk-go-wrapper/[サービス名]"
)func main() {
    // コンフィグの作成
    conf := config.Config{
        /* クレデンシャル情報を直接指定する場合は以下を指定 */
        AccessKey: "[アクセスキーID]",
        SecretKey: "[シークレットアクセスキー]",
        Region: "ap-north-east1",/* Shared credentialファイルを使う場合は以下を指定 */
        // Filename: "[ファイル名]",
        // Profile:  "[プロファイル名]",/* その他のオプション */
        // Endpoint:  "http://localhost:8000", // エンドポイントを指定する場合に使用
        // DefaultPrefix: "dev",   // SQSキューやDynamoDBテーブルに付けるプリフィクス
        // S3ForcePathStyle: true, // S3でバケット指定にパススタイルを使う
    }cli, err := [サービス名].New(conf)
    if err != nil {
        panic(err)
    }
    // 各サービスの処理が続く...
}ラッパーと公式ではクレデンシャルの優先順位が異なっています。
コンパイル済みのバイナリでも容易に動作を変えられるように、環境変数が一番優先されるようにしています。SQS公式の例と同様に、まずはSQSを使ってみます。SQS キューの作成(CreateQueue)キューの作成は以下のようにして行います。import (
    "github.com/evalphobia/aws-sdk-go-wrapper/sqs"
)// (中略)func createQueue() {
    // SQSクライアントの作成
    svc, err := sqs.New(conf)
    if err != nil {
        panic(err)
    }// 既に作成済みなら何もせずに終了
    ok, err := svc.IsExistQueue("[キュー名]")
    if ok {
        return
    }// CreateQueueの実行
    err = svc.CreateQueueWithName("[キュー名]")
    if err != nil {
        panic(err)
    }
}SQS キューの取得(GetQueue)キューURLの取得は以下のようにして行います。import (
    "github.com/evalphobia/aws-sdk-go-wrapper/sqs"
)func getQueue() {
    // SQSクライアントの作成
    svc, err := sqs.New(conf)
    if err != nil {
        panic(err)
    }// キューの取得
    queue, err := svc.GetQueue("[キュー名]")
    if err != nil {
        panic(err)
    }
}取得した queue はSQSキューを表すオブジェクトになります。
メッセージの操作で使います。SQS キューの削除(DeleteQueue)キューの削除は以下のようにして行います。import (
    "github.com/evalphobia/aws-sdk-go-wrapper/sqs"
)func deleteQueue() {
    // SQSクライアントの作成
    svc, err := sqs.New(conf)
    if err != nil {
        panic(err)
    }// キューの削除
    err = svc.DeleteQueue("[キュー名]")
    if err != nil {
        panic(err)
    }
}SQS メッセージの送信(SendMessage)メッセージの送信は以下のようにして行います。import (
    "github.com/evalphobia/aws-sdk-go-wrapper/sqs"
)func sendMessage() {
    // SQSクライアントの作成
    svc, err := sqs.New(conf)
    if err != nil {
        panic(err)
    }// キューの取得
    queue, err = svc.GetQueue("")
    if err != nil {
        panic(err)
    }// スプールへメッセージを追加 (1)
    queue.AddMessage("メッセージその1")// スプールへメッセージを追加 (2)
    mapData := map[string]interface{}{
        "key": "メッセージその2",
    }
    queue.AddMessageMap(mapData)// スプールへメッセージを追加 (3)
    structData := struct{
        Key string `json:"key"`
    }{
        Key: "メッセージその3",
    }
    queue.AddMessageJSONMarshal(structData)// スプール内のメッセージを全て送信する
    err = queue.Send()
    if err != nil {
        panic(err)
    }
}メッセージの送信には、queue.AddMessage()queue.Send() を使用します。
json.Marshal() でJSON文字列にしたい場合は、queue.AddMessageMap()queue.AddMessageJSONMarshal() を使ってください。SQS メッセージの受信(ReceiveMessage)メッセージの受信は以下のようにして行います。import (
    "fmt"
    "github.com/evalphobia/aws-sdk-go-wrapper/sqs"
)func sendMessage() {
    // SQSクライアントの作成
    svc, err := sqs.New(conf)
    if err != nil {
        panic(err)
    }// キューの取得
    queue, err = svc.GetQueue("[キュー名]")
    if err != nil {
        panic(err)
    }// メッセージを1件だけ取得
    msg, err := queue.FetchOne()
    if err != nil {
        panic(err)
    }
    fmt.Println(msg.Body()) // メッセージ内容を表示// メッセージを最大10件取得
    msgList, err := queue.Fetch(10)
    if err != nil {
        panic(err)
    }
    for _, m := range msgList {
        fmt.Println(m.Body()) // メッセージ内容を表示
    }// Fetch実行時に自動削除をするオプションを設定
    queue.AutoDel(true)// メッセージを最大10件取得(レスポンスはメッセージ内容のスライス)
    bodyList := queue.FetchBody(10)
    for _, body := range bodyList {
        fmt.Println(bodyList) // メッセージ内容を表示
    }
}基本的な使い方は queue.Fetch(num)numに件数を入れて取得します。FetchBody(num)FetchBodyOne()を使うと、メッセージ内容のみ取得できますが、
このままだと取り出したメッセージの削除ができないため、事前に queue.AutoDel(true) を指定し、
取得した際に自動削除されるようにしておきます。SQS メッセージの削除(DeleteMessage)メッセージの削除は以下のようにして行います。import (
    "github.com/evalphobia/aws-sdk-go-wrapper/sqs"
)func sendMessage() {
    // SQSクライアントの作成
    svc, err := sqs.New(conf)
    if err != nil {
        panic(err)
    }// キューの取得
    queue, err = svc.GetQueue("[キュー名]")
    if err != nil {
        panic(err)
    }// メッセージを最大10件取得
    msgList, err := queue.Fetch(10)
    if err != nil {
        panic(err)
    }// 取得したメッセージの削除
    for _, m := range msgList {
        queue.DeleteMessage(m)
    }
}queue.DeleteMessage() にメッセージを渡すと削除できます。
(queue.AutoDel(true) を指定しておくと、queue.Fetch() 実行時に自動で削除されます)DynamoDB公式の例と同様、DynamoDBも使ってみましょう。DynamoDB テーブルの作成テーブルの作成は以下のようにして行います。import (
    "github.com/evalphobia/aws-sdk-go-wrapper/dynamodb"
)func createTable() {
    // DynamoDBクライアントの作成
    svc, err := dynamodb.New(conf)
    if err != nil {
        panic(err)
    }// String型のidというハッシュキーを持つテーブル定義オブジェクトを作成
    design := dynamodb.NewTableDesignWithHashKeyS("table_name", "id")//テーブル定義を追加
    design.AddRangeKeyN("time")                        // Number型のtimeというレンジキーを追加
    design.AddLSIN("age-index", "age")                 // Number型のageというレンジキーを持つ、age-indexというローカルセカンダリインデックスを追加
    design.AddGSIN("update-index", "updated_at")       // Number型のupdated_atというハッシュキーを持つ、update-indexというグローバルセカンダリインデックスを追加
    design.AddGSISN("country-index", "country", "age") // String型のcountryというハッシュキーとNumber型のageというレンジキーを持つ、country-indexというグローバルセカンダリインデックスを追加err := svc.CreateTable(design)
    if err != nil {
        panic(err)
    }
}この例では、
というテーブルを作成しています。DynamoDB テーブルの情報取得(DescribeTable)テーブルの情報取得は以下のようにして行います。import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/service/dynamodb"
)func main() {
    // DynamoDBクライアントの作成
    svc := dynamodb.New(sess)// テーブルの取得
    table, err := svc.GetTable("table_name")
    if err != nil {
        panic(err)
    }
}取得したテーブルのオブジェクトは項目の追加や取得に使用します。DynamoDB 項目のPUT(PutItem)項目のPUTは以下のようにして行います。// DynamoDBクライアントの作成
    svc := dynamodb.New(sess)// テーブルの取得
    table, err := svc.GetTable("table_name")
    if err != nil {
        panic(err)
    }// 項目オブジェクトの作成
    item := dynamodb.NewPutItem()
    item.AddAttribute("id", "A001")
    item.AddAttribute("time", time.Now().Unix())
    item.AddAttribute("age", 18)
    item.AddAttribute("country", "jp")
    item.AddAttribute("updated_at", time.Now().Unix())
    item.AddAttribute("status", 1)// スプールに項目を追加
    table.AddItem(item)// スプール内の項目を全てPUTする
    err = table.Put()
    if err != nil {
        panic(err)
    }
}dynamodb.NewPutItem() で項目オブジェクトを作成し、table.AddItem() で項目を書き込みスプールへ追加します。
そしてtable.Put()で書き込みスプール内の項目をPutします。なお、svc.PutAll() を使うと、全てのテーブルの書き込みスプール内の項目をPutします。DynamoDB 項目の取得(GetItem)項目の取得には以下のようになります。import (
    "github.com/aws/aws-sdk-go/service/dynamodb"
)func main() {
    // DynamoDBクライアントの作成
    svc := dynamodb.New(sess)// テーブルの取得
    table, err := svc.GetTable("table_name")
    if err != nil {
        panic(err)
    }// 項目の取得
    id := "A001"
    time := 1
    item, err := table.GetOne(id, time)
    if err != nil {
        panic(err)
    }
}table.GetOne(hashKey, rangeKey) として、項目を取得します。
ハッシュキーしかないテーブルの場合、rangeKeyは省略できます。取得した項目はmap[string]interface{}となっています。DynamoDB 項目の取得(QueryとScan)ここからようやく、DynamoDBの便利APIのQueryとScanを使っていきます。import (
    "github.com/evalphobia/aws-sdk-go-wrapper/dynamodb"
)func main() {
    // DynamoDBクライアントの作成
    svc, err := dynamodb.New(conf)
    if err != nil {
        panic(err)
    }// テーブルの取得
    table, err := svc.GetTable("MyDynamoTable")
    if err != nil {
        panic(err)
    }// 項目をQueryで取得
    cond := table.NewConditionList()
    cond.AndEQ("country", "jp")
    cond.FilterLT("age", 20)
    cond.SetLimit(100)
    result, err := table.Query(cond) // Queryの実行
    if err != nil {
        panic(err)
    }// 結果を格納する構造体
    type User struct {
        ID     int64 `dynamodb:"id"`
        Age    int   `dynamodb:"age"`
        Status int   `dynamodb:"status"`
    }var list []*User
    err = result.Unmarshal(&list) // 取得結果をlistへマッピング
    if err != nil {
        panic(err)
    }// 項目をScanで取得
    cond = table.NewConditionList()
    cond.SetLimit(1000)
    cond.FilterEQ("status", 2)
    result, err = table.ScanWithCondition(cond) //Scanの実行
    if err != nil {
        panic(err)
    }data := result.ToSliceMap() // 取得結果を[]map[string]interface{}へ変換// 項目をScanで取得(前回取得した箇所の次から取得)
    cond.SetStartKey(result.LastEvaluatedKey) // 開始位置を指定
    result, err = table.ScanWithCondition(cond) //Scanの実行
    if err != nil {
        panic(err)
    }data = append(data, result.ToSliceMap()...) // 2回目の取得結果を1回目の結果へ追加
}Queryはインデックスを使い複数の項目を一気に取得できるので、よく使われると思います。
Scanはスループットを消費するため使う機会は限られてくるかもしれませんが、集計・バッチ用途等で使うことがあるかもしれません。まとめいかがでしょうか。
使い方は何となくおわかりいただけたかと思います。公式の場合は、セッションを作成し、各サービスのクライアントを作成します。
そしてクライアントの使用したいAPIに対してAPI名+Inputという構造体のパラメータを渡します。ラッパーの場合はコンフィグを作成し、各サービスのクライアントを作成します。ラッパーは弊社の用途に合わせて作ってあるため、いくつか足りないAPIがありますが、
組み込み型のポインタや煩雑なパラメータを直接扱わなくて済むため、実装が楽になると思います。
もし用途に合うようであれば、使ってみてください。(そして足りない機能・サービスのプルリクエストをもらえると助かります!)

Eureka Engineering

Learn about Eureka’s engineering efforts, product developments and more.

eureka, Inc.

Written by

Learn more about how Eureka technology and engineering

Eureka Engineering

Learn about Eureka’s engineering efforts, product developments and more.