Go での DynamoDB GetItem(AWS SDK v2)
AWS SDK for Go v2 では、アイテムは map[string]types.AttributeValue であり、types.AttributeValue は封印されたインターフェースです。実装は SDK が同梱する 10 個の AttributeValueMember* 構造体だけです。これらでキーを書くのは簡単です。値を読み出すところで、Go は他のどの SDK とも違ってきます。
client.GetItem は、他と同じくプライマリキー全体を必要とします。
コード
package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)
func main() {
ctx := context.TODO()
cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1"))
if err != nil {
log.Fatalf("load config: %v", err)
}
client := dynamodb.NewFromConfig(cfg)
out, err := client.GetItem(ctx, &dynamodb.GetItemInput{
TableName: aws.String("Music"),
Key: map[string]types.AttributeValue{
"Artist": &types.AttributeValueMemberS{Value: "Arturo Sandoval"},
"SongTitle": &types.AttributeValueMemberS{Value: "Cubano Chant"},
},
ProjectionExpression: aws.String("#proj0, #proj1, #proj2, #proj3"),
ExpressionAttributeNames: map[string]string{
"#proj0": "Artist",
"#proj1": "SongTitle",
"#proj2": "AlbumTitle",
"#proj3": "Year",
},
})
if err != nil {
log.Fatalf("get item: %v", err)
}
if out.Item == nil {
fmt.Println("Item not found")
return
}
fmt.Println(out.Item)
}解説
- スカラーはポインタ —
TableName、ProjectionExpression、ConsistentReadは*stringや*boolです。SDK が「未設定」とゼロ値を区別できるようにするためです。aws.String、aws.Bool、aws.Int32はそのためだけに存在します。 - 数値は文字列で届く —
AttributeValueMemberN.Valueはstringです。DynamoDB がワイヤ上で数値を文字列として送るからです。Yearを読むにはout.Item["Year"].(*types.AttributeValueMemberN)としてからstrconv.Atoiします。型アサーションはカンマ ok 形式を使ってください。素の形式は、属性が存在しないときや型が違うときに panic します。 - 出口は
attributevalue.UnmarshalMap—github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalueにあり、アイテム全体をdynamodbavタグ付きの構造体にマッピングし、文字列から数値への変換も行ってくれます。アイテムの属性が数個を超えた時点で、手を伸ばす価値があります。 - ヒットしなければ
out.Itemはnilで、errもnilです。両者を区別する必要がなければ、len(out.Item) == 0で nil と空の両方をカバーできます。 - エラーは
errors.Asで照合 — Go v2 はサービス側の障害を Smithy のオペレーションエラーでラップするので、err == …もerr.Error()の文字列一致も、どちらも黙って失敗します。var nf *types.ResourceNotFoundExceptionを宣言して、そのアドレスを渡してください。 ConsistentRead: aws.Bool(true)は読み取りコストを倍にし、GSI では拒否されます。上の#projエイリアスも飾りではありません。Yearは予約語なので、それを直接指定した射影は拒否されます。
ビジュアルに行う
AttributeValueMember* 形式と素の JSON のあいだの変換は、Go では常につきまとう税金です。DynamoDB JSON コンバータは、アイテムを 1 件読むか貼り付けるだけでよいときに、その往復をブラウザ上で片付けてくれます。
DynoTable なら、アイテムは代わりに普通の行として表示され、グリッドの背後にあるクエリを、ここで使ったものと同じ SDK v2 の型に基づく Go プログラムとしてエクスポートできます。DynoTable をダウンロードしてください。
関連する例
- Java での DynamoDB GetItem — AWS SDK for Java 2.x による同じ読み取り。
- Go での DynamoDB Query — 1 アイテムではなくパーティション全体を読む。
- DynamoDB のパーティションキーの仕組み — なぜ
GetItemにキー全体が必要なのか。 - DynamoDB ResourceNotFoundException — ここで最初に出る定番のエラー。テーブル名かリージョンの誤りです。
- 「The provided key element does not match the schema」 — 渡したキーがテーブルのキースキーマと一致していない。
参考資料
- GetItem — Amazon DynamoDB API Reference
- Use GetItem with an AWS SDK or CLI — Amazon DynamoDB Developer Guide
- dynamodb package — AWS SDK for Go v2 (pkg.go.dev)
- dynamodb/types package — AWS SDK for Go v2 (pkg.go.dev)
- attributevalue package — AWS SDK for Go v2 (pkg.go.dev)
- Read consistency — Amazon DynamoDB Developer Guide
最終検証日 2026-07-28、上記にリンクした公式 AWS ドキュメントに照らして確認しました。