DynamoDB PutItem in Go (AWS SDK v2)

PutItem writes a whole item, creating it or replacing any existing item with the same primary key. In AWS SDK for Go v2 you call client.PutItem with a dynamodb.PutItemInput whose Item map holds every attribute as a typed value from the types package.

Code

package main

import (
	"context"
	"errors"
	"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)

	_, err = client.PutItem(ctx, &dynamodb.PutItemInput{
		TableName: aws.String("Music"),
		Item: map[string]types.AttributeValue{
			"Artist":     &types.AttributeValueMemberS{Value: "Arturo Sandoval"},
			"SongTitle":  &types.AttributeValueMemberS{Value: "Cubano Chant"},
			"AlbumTitle": &types.AttributeValueMemberS{Value: "Danzon"},
			"Year":       &types.AttributeValueMemberN{Value: "1994"},
			"Awards":     &types.AttributeValueMemberN{Value: "0"},
		},
		ConditionExpression: aws.String("attribute_not_exists(#cond0) AND attribute_not_exists(#cond1)"),
		ExpressionAttributeNames: map[string]string{
			"#cond0": "Artist",
			"#cond1": "SongTitle",
		},
	})
	if err != nil {
		var ccf *types.ConditionalCheckFailedException
		if errors.As(err, &ccf) {
			fmt.Println("A song with that key already exists — not overwritten")
			return
		}
		log.Fatalf("put item: %v", err)
	}
	fmt.Println("Song written")
}

To build the Item map from a plain Go struct instead, use attributevalue.MarshalMap from github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue.

Explanation

  • Item — must contain the table's full primary key, plus any other attributes. Numbers are strings inside AttributeValueMemberN ({Value: "1994"}).
  • Put replaces — without a condition, PutItem silently overwrites an existing item with the same key. Use UpdateItem to change a few attributes without clobbering the rest.
  • ConditionExpressionattribute_not_exists(...) on the key attributes makes the write a create-only insert; the write fails with ConditionalCheckFailedException if the item already exists. This is DynamoDB's optimistic-locking primitive. The #cond0/#cond1 aliases resolve to Artist/SongTitle via ExpressionAttributeNames (reserved-word-safe).
  • errors.As — the Go SDK wraps service errors, so match the typed *types.ConditionalCheckFailedException with errors.As, never by string comparison.
  • To get the overwritten item back, set ReturnValues: types.ReturnValueAllOld.

Do it visually

Writing a conditional put by hand? The DynamoDB Expression Builder assembles the ConditionExpression and copies the code.

To add and edit items in a GUI — a form per attribute, type pickers, and copy-as-code — download DynoTable.

References

Last verified 2026-07-13 against the official AWS documentation linked above.

Lavora con DynamoDB senza la Console

DynoTable è un client desktop veloce per DynamoDB — sfoglia le tabelle, esegui query in stile SQL e modifica gli Item localmente.