DynamoDB GetItem in Go (AWS SDK v2)
In AWS SDK for Go v2 an item is a map[string]types.AttributeValue, and types.AttributeValue is a sealed interface: the only implementations are the ten AttributeValueMember* structs the SDK ships. Writing a key with them is easy. Reading values back out is where Go diverges from every other SDK.
client.GetItem still wants the full primary key, same as everywhere else.
Code
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)
}Explanation
- Scalars are pointers —
TableName,ProjectionExpressionandConsistentReadare*stringand*boolso the SDK can tell "unset" from the zero value.aws.String,aws.Boolandaws.Int32exist for that and nothing else. - Numbers arrive as strings —
AttributeValueMemberN.Valueis astring, because DynamoDB sends numbers as strings on the wire. ReadingYearmeansout.Item["Year"].(*types.AttributeValueMemberN)and thenstrconv.Atoi. Use the comma-ok form of the assertion; the bare form panics when the attribute is missing or a different type. attributevalue.UnmarshalMapis the way out — fromgithub.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue, it maps the whole item onto a struct withdynamodbavtags and does the string-to-number conversion. Worth reaching for the moment an item has more than a couple of attributes.out.Itemisnilon a miss, anderrisniltoo.len(out.Item) == 0covers both nil and empty if you do not need to distinguish them.- Match errors with
errors.As— Go v2 wraps service faults in a Smithy operation error, soerr == …and string matching onerr.Error()both silently fail. Declarevar nf *types.ResourceNotFoundExceptionand pass its address. ConsistentRead: aws.Bool(true)doubles the read cost and is rejected on a GSI. The#projaliases above are not decoration either:Yearis a reserved word, and a projection naming it directly is refused.
Do it visually
Translating between the AttributeValueMember* form and plain JSON is a constant tax in Go. The DynamoDB JSON converter does that round trip in the browser when you only need to read or paste one item.
DynoTable shows items as ordinary rows instead, and exports the query behind the grid as a Go program built on these same SDK v2 types. Download DynoTable.
Related examples
- DynamoDB GetItem in Java — the same read with AWS SDK for Java 2.x.
- DynamoDB Query in Go — read a whole partition instead of one item.
- How DynamoDB partition keys work — why
GetItemneeds the full key. - DynamoDB ResourceNotFoundException — the usual first error here: wrong table name or region.
- "The provided key element does not match the schema" — the key you pass doesn't match the table's key schema.
References
- 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
Last verified 2026-07-28 against the official AWS documentation linked above.