Go 中的 DynamoDB GetItem(AWS SDK v2)
在 AWS SDK for Go v2 里,一个项目就是 map[string]types.AttributeValue,而 types.AttributeValue 是一个密封接口:唯一的实现就是 SDK 自带的那十个 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。请用带 comma-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 转换器会在浏览器里完成这趟往返。
DynoTable 则把项目显示成普通的行,并把结果网格背后的查询导出为一个基于这套 SDK v2 类型构建的 Go 程序。下载 DynoTable。
相关示例
- Java 中的 DynamoDB GetItem——用 AWS SDK for Java 2.x 完成同样的读取。
- Go 中的 DynamoDB Query——读取整个分区而不是单个项目。
- 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 官方文档。