Go'da DynamoDB UpdateItem (AWS SDK v2)

UpdateItem Go'da dolambaçsızdır; tuhaf olan kısım, map[string]types.AttributeValue'nun bir arayüz eşlemesi olmasıdır; dolayısıyla hem gönderdiğiniz değerler hem de geri aldıklarınız dokuz üye struct'tan birine işaretçidir. Tek bir tasarım tercihi aşağıdaki sürtünmenin çoğunu açıklar ve bu parçacıktaki fmt.Println'in öğenizi yazdırmaması gerçeğiyle başlar.

Kod

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
}

Açıklama

  • AttributeValueMemberN.Value sayısal bir tür değil, bir string'dir ve attributevalue.Marshal onu öyle tutar: int64(9007199254740993) tam olarak "9007199254740993" olarak marshal edilir. DynamoDB sayıları 38 hanelik hassasiyet taşır — herhangi bir Go float'ından fazla; dolayısıyla SDK asla dönüştürmez. Ayrıştırmayı sınırda, bilerek siz yaparsınız.

  • ReturnValues: types.ReturnValueAllNew — sabitin değeri birebir "ALL_NEW"'dir. Belgeler yerine türden okumayı tercih ederseniz, types.ReturnValueAllNew.Values() beşinin hepsini listeler (NONE, ALL_OLD, UPDATED_OLD, ALL_NEW, UPDATED_NEW).

  • UpdateExpression kendinizin kurduğu bir *string'dir ya da aşağıdaki expression paketine devredersiniz. Her iki durumda da tek ayrıştırıcı DynamoDB'dir: ADD #upd2 :updValue2 atomik artırımı verir, bir ConditionExpression içindeki attribute_exists(Artist) çağrıyı bir upsert yerine yalnızca-güncelleme hâline getirir ve yan tümce grameri güncelleme ifadeleri sayfasındadır.

  • ValidationException'ın Go türü yoktur. types/errors.go, ConditionalCheckFailedException, TransactionCanceledException, ProvisionedThroughputExceededException ve TransactionConflictException dahil 35 hata struct'ı tanımlar. Doğrulama başarısızlıkları bunların arasında değildir; dolayısıyla kötü bir ifade, yalnızca dizeye bakarak tanıyabileceğiniz genel bir smithy.APIError olarak yüzeye çıkar:

    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: Year

    Aşağıdaki modellenmiş ConditionalCheckFailedException'ın almadığı api error önekine dikkat edin. Varlığı, burada somut bir türe karşı errors.As kullanmanın size yardımcı olmayacağının iyi bir işaretidir.

  • Buna karşılık başarısız bir koşul gerçek bir türdür. var ccf *types.ConditionalCheckFailedException; errors.As(err, &ccf) eşleşir ve girdide ReturnValuesOnConditionCheckFailure: types.ReturnValuesOnConditionCheckFailureAllOld varken ccf.Item, öğe gerçekte nasıl olduysa öyle dolu gelir. ccf.ErrorMessage(), err.Error()'ın önüne eklediği taşıma girişi olmadan çıplak The conditional request failed mesajıdır.

Sonucu geri okumak

Bir arayüz eşlemesi üzerinde fmt.Println(out.Attributes) adresleri yazdırır:

map[Artist:0x1c8cf589e060 Awards:0x1c8cf589e078 Genre:0x1c8cf589e090 SongTitle:0x1c8cf589e0c0 Year:0x1c8cf589e0a8]

İki çıkış yolu var. Çoğu kodun yapması gereken şey olan, bir struct'a unmarshal etmek:

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}

Ya da önemsediğiniz tek üyeyi tür doğrulamasıyla almak — ve .Value'nun bir dize olduğunu unutmamak:

n, ok := out.Attributes["Awards"].(*types.AttributeValueMemberN)
if ok {
	awards, _ := strconv.Atoi(n.Value) // "1" -> 1
	fmt.Println(awards)
}

İfadeyi expression paketi yazsın

Go, bu sitede UpdateExpression'ı sizin yerinize üretecek tek SDK'dır. feature/dynamodb/expression yan tümceleri ve her iki eşlemeyi de birlikte kurar:

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()

Çıkan şey yazdığınız şey değildir:

UpdateExpression: ADD #0 :0
SET #1 = :1, #2 = :2

Names: map[#0:Awards #1:Genre #2:Year]

Kurucu yan tümceleri yeniden sıraladı, aralarına bir satır sonu koydu ve yer tutucuları kendisi numaralandırdı; dolayısıyla #0, andığınız ilk ad değil Awards'tır. Aşağı akışta hiçbir şey bunu önemsemez, ama dizeler düzenlemeler arasında kararlı değildir — bu da onları testlerde doğrulanacak kötü bir şey yapar. expr.Update(), expr.Names() ve expr.Values()'i doğrudan UpdateItemInput'a geçirin ve onlara hiç bakmayın.

İyi yanı, her ada takma ad vermesidir; böylece ayrılmış sözcükler artık sahaya sürebileceğiniz bir hata sınıfı olmaktan çıkar. İfadeyi bunun yerine elle yazıyorsanız, öznitelik adlarını önce DynamoDB ayrılmış sözcük denetleyicisinden geçirin — AWS listesinde 573 girdi var ve Year, Name ile Status hepsi listede. Ve bir öğeye arayüz işaretçilerinden oluşan bir eşleme olarak değil de veri olarak bakmayı tercih ederseniz, DynoTable'ı indirin.

İlgili örnekler

Kaynaklar

En son 2026-07-28 tarihinde yukarıda bağlantısı verilen resmi AWS belgelerine karşı doğrulandı.

Console olmadan DynamoDB ile çalış

DynamoDB’nin çalıştıramadığı gerçek SQL’i çalıştıran hızlı bir DynamoDB masaüstü istemcisi — JOINs, GROUP BY, toplamalar — görsel düzenleme ve kendi Bedrock anahtarların üzerinde bir yapay zekâ aracısıyla.

30 günlük ücretsiz deneme, kredi kartı yok — ardından süre sınırı olmayan Ücretsiz plan.