Go言語学習26日目:POSTリクエストでDynamoDBにデータ登録するAPIを作ってみた【AWS SDK v2】

Go言語学習26日目

Go言語学習スケジュールも26日目まできました。。
今日は、Goで作ったWebサーバーにPOSTエンドポイントを追加して、DynamoDBにデータを書き込むAPIを実装してみます!

これまででAWS SDKの初期化やPutItemの基本は触れてきましたが、
今回は「実際にクライアントからデータを受け取って登録するWeb API」という形でまとめていきます!


今日の目標

POSTリクエストでJSONを受け取り、DynamoDB(テーブル名: Go-Practice-Users)にデータを登録するAPIを作成!
  • 使うキー:UserID(パーティションキー)+ sortKey(ソートキー、固定で"User")
  • JSONで受け取るのは UserIDNameAge
  • クライアントは curl や Postman など想定

💻 完成コード(main.go)

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "net/http"

    "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"
    "github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue"
)

type Item struct {
    UserID  string `json:"UserID" dynamodbav:"UserID"`
    Name    string `json:"Name" dynamodbav:"Name"`
    Age     int    `json:"Age" dynamodbav:"Age"`
    SortKey string `json:"-" dynamodbav:"sortKey"` // 固定値("User")として保存
}

func main() {
    svc := initDynamoClient()

    http.HandleFunc("/items", func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodPost {
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
            return
        }

        var item Item
        if err := json.NewDecoder(r.Body).Decode(&item); err != nil {
            http.Error(w, "Invalid request body", http.StatusBadRequest)
            return
        }

        if item.UserID == "" || item.Name == "" {
            http.Error(w, "UserIDとNameは必須です", http.StatusBadRequest)
            return
        }

        item.SortKey = "User"

        av, err := attributevalue.MarshalMap(item)
        if err != nil {
            http.Error(w, "Marshal失敗", http.StatusInternalServerError)
            return
        }

        _, err = svc.PutItem(context.TODO(), &dynamodb.PutItemInput{
            TableName: aws.String("Go-Practice-Users"),
            Item:      av,
        })
        if err != nil {
            http.Error(w, "PutItem失敗", http.StatusInternalServerError)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(http.StatusCreated)
        fmt.Fprint(w, `{"message":"Item saved"}`)
    })

    fmt.Println("🚀 サーバー起動中:http://localhost:8080/items")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func initDynamoClient() *dynamodb.Client {
    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        log.Fatalf("AWS設定の読み込みに失敗: %v", err)
    }
    return dynamodb.NewFromConfig(cfg)
}

🧪 curlでテスト!

curl -X POST http://localhost:8080/items -H "Content-Type: application/json" -d "{\"UserID\": \"u001\", \"Name\": \"テスト太郎\", \"Age\": 25}"

DynamoDBの Go-Practice-Users テーブルに以下のデータが登録されました。

UserID sortKey Name Age
u001 User テスト太郎 25

📝 注意点と補足

  • テーブル構成(UserID + sortKey)に合わせて sortKey: "User" を固定値として追加
  • JSON入力に sortKey は含まれないよう json:"-" で制御
  • AWS認証情報、テーブル作成、IAM権限(PutItem可)が正しく設定されている前提です

📘 今日の学びポイント

  • POSTエンドポイントからのデータ登録の流れを構築
  • DynamoDBの複合キー(Partition + Sort)に対応
  • JSON⇔構造体⇔DynamoDBマッピングの感覚がつかめた
  • Web API開発としても、実用的なステップを踏めた!

以上となります。引き続きよろしくお願いいたします。