DynamoDB UpdateItem di Go (AWS SDK v2)
UpdateItem cukup lugas di Go; bagian yang canggung adalah map[string]types.AttributeValue merupakan map berisi interface, jadi baik nilai yang Anda kirim maupun yang Anda terima kembali adalah pointer ke salah satu dari sembilan struct anggota. Satu keputusan desain itulah yang menjelaskan sebagian besar gesekan di bawah ini, dimulai dari fakta bahwa fmt.Println di potongan kode ini tidak mencetak item Anda.
Kode
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.UpdateItem(ctx, &dynamodb.UpdateItemInput{
TableName: aws.String("Music"),
Key: map[string]types.AttributeValue{
"Artist": &types.AttributeValueMemberS{Value: "Arturo Sandoval"},
"SongTitle": &types.AttributeValueMemberS{Value: "Cubano Chant"},
},
UpdateExpression: aws.String("SET #upd0 = :updValue0, #upd1 = :updValue1 ADD #upd2 :updValue2"),
ExpressionAttributeNames: map[string]string{
"#upd0": "Genre",
"#upd1": "Year",
"#upd2": "Awards",
},
ExpressionAttributeValues: map[string]types.AttributeValue{
":updValue0": &types.AttributeValueMemberS{Value: "Latin Jazz"},
":updValue1": &types.AttributeValueMemberN{Value: "1994"},
":updValue2": &types.AttributeValueMemberN{Value: "1"},
},
ReturnValues: types.ReturnValueAllNew,
})
if err != nil {
log.Fatalf("update item: %v", err)
}
fmt.Println(out.Attributes) // the item after the update
}Penjelasan
AttributeValueMemberN.Valuebertipestring, bukan tipe numerik, danattributevalue.Marshalmempertahankannya begitu:int64(9007199254740993)di-marshal menjadi"9007199254740993"persis. Angka DynamoDB membawa presisi 38 digit, lebih dari float Go mana pun, jadi SDK tidak pernah mengonversinya. Andalah yang melakukan parsing, di tepi, secara sadar.ReturnValues: types.ReturnValueAllNew— nilai konstanta itu adalah literal"ALL_NEW".types.ReturnValueAllNew.Values()mendaftar kelimanya (NONE,ALL_OLD,UPDATED_OLD,ALL_NEW,UPDATED_NEW) kalau Anda lebih suka membacanya dari tipenya ketimbang dari dokumentasi.UpdateExpressionadalah*stringyang Anda bangun sendiri, atau Anda serahkan ke paketexpressiondi bawah. Bagaimanapun, DynamoDB adalah satu-satunya parser:ADD #upd2 :updValue2memberi penambahan atomik,attribute_exists(Artist)di sebuahConditionExpressionmembuat panggilannya hanya-update alih-alih upsert, dan tata bahasa klausanya ada di update expression.ValidationExceptiontidak punya tipe Go.types/errors.gomendefinisikan 35 struct error, termasukConditionalCheckFailedException,TransactionCanceledException,ProvisionedThroughputExceededException, danTransactionConflictException. Kegagalan validasi tidak termasuk di antaranya, jadi expression yang buruk muncul sebagaismithy.APIErrorgenerik yang hanya bisa Anda kenali lewat string:operation error DynamoDB: UpdateItem, https response error StatusCode: 400, RequestID: 702d67f1-4f15-43dc-b3e9-cea691878801, api error ValidationException: Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: YearPerhatikan awalan
api error, yang tidak didapatConditionalCheckFailedExceptionbermodel di bawah. Kehadirannya adalah sinyal yang lumayan bahwaerrors.Asterhadap tipe konkret tidak akan menolong Anda di sini.Kondisi yang gagal, sebaliknya, adalah tipe sungguhan.
var ccf *types.ConditionalCheckFailedException; errors.As(err, &ccf)cocok, dan denganReturnValuesOnConditionCheckFailure: types.ReturnValuesOnConditionCheckFailureAllOldpada input,ccf.Itemdatang terisi item sebagaimana adanya.ccf.ErrorMessage()adalahThe conditional request failedyang polos, tanpa pembuka transport yang ditambahkanerr.Error()di depannya.
Membaca hasilnya kembali
fmt.Println(out.Attributes) pada map berisi interface mencetak alamat:
map[Artist:0x1c8cf589e060 Awards:0x1c8cf589e078 Genre:0x1c8cf589e090 SongTitle:0x1c8cf589e0c0 Year:0x1c8cf589e0a8]Ada dua jalan keluar. Lakukan unmarshal ke sebuah struct, yang seharusnya dilakukan kebanyakan kode:
var song struct {
Artist string
Genre string
Year int
Awards int
}
err = attributevalue.UnmarshalMap(out.Attributes, &song)
// {Artist:Arturo Sandoval Genre:Latin Jazz Year:1994 Awards:1}Atau lakukan type assertion pada satu anggota yang Anda pedulikan, dan ingat bahwa .Value adalah string:
n, ok := out.Attributes["Awards"].(*types.AttributeValueMemberN)
if ok {
awards, _ := strconv.Atoi(n.Value) // "1" -> 1
fmt.Println(awards)
}Biarkan paket expression yang menuliskannya
Go adalah satu-satunya SDK di situs ini yang mau membuatkan UpdateExpression untuk Anda. feature/dynamodb/expression menyusun klausa dan kedua map-nya:
upd := expression.Set(expression.Name("Genre"), expression.Value("Latin Jazz")).
Set(expression.Name("Year"), expression.Value(1994)).
Add(expression.Name("Awards"), expression.Value(1))
expr, _ := expression.NewBuilder().WithUpdate(upd).Build()Yang keluar bukan yang Anda tulis:
UpdateExpression: ADD #0 :0
SET #1 = :1, #2 = :2
Names: map[#0:Awards #1:Genre #2:Year]Builder-nya menyusun ulang klausa, memisahkannya dengan baris baru, dan menomori sendiri placeholder-nya, sehingga #0 adalah Awards, bukan nama pertama yang Anda sebut. Tak ada yang di hilir memedulikannya, tetapi string-nya tidak stabil antar-penyuntingan, yang membuatnya buruk untuk dijadikan bahan assert di tes. Oper expr.Update(), expr.Names(), dan expr.Values() langsung ke UpdateItemInput lalu jangan pernah menengoknya lagi.
Sisi baiknya, ia meng-alias setiap nama, sehingga reserved word berhenti menjadi kelas bug yang bisa Anda kirim ke produksi. Kalau Anda menulis expression-nya dengan tangan, lewatkan dulu nama atributnya melalui pemeriksa reserved word DynamoDB — daftar AWS punya 573 entri dan Year, Name, serta Status semuanya ada di sana. Dan kalau Anda lebih suka melihat item sebagai data ketimbang sebagai map berisi pointer interface, unduh DynoTable.
Contoh terkait
- DynamoDB UpdateItem di Java — update yang sama dengan AWS SDK for Java 2.x.
- DynamoDB PutItem di Go — mengganti seluruh item sebagai gantinya.
- Update expression DynamoDB —
SET,ADD,REMOVE,DELETE, dan idiomnya. - Memahami ReturnValues — apa yang diberikan tiap opsi
ReturnValues. - "Attribute name is a reserved keyword" — mengapa peta alias di sini tidak opsional.
- Error sintaks "Invalid UpdateExpression" — kesalahan sintaks SET/ADD yang umum, diuraikan.
Referensi
- UpdateItem — Amazon DynamoDB API Reference
- Use UpdateItem 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)
- expression package — AWS SDK for Go v2 (pkg.go.dev)
- Update expressions — Amazon DynamoDB Developer Guide
Terakhir diverifikasi 2026-07-28 terhadap dokumentasi resmi AWS yang ditautkan di atas.