Go言語入門:RESTful API の開発 Vol.2

スポンサーリンク
Go言語入門:RESTful API の開発 Vol.2 ノウハウ
Go言語入門:RESTful API の開発 Vol.2
この記事は約12分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

今日は、先日の記事に引き続き、GolangでRESTful APIを開発する方法についてご紹介します。

スポンサーリンク

概要

本記事は前回の記事からの続きになります。前回の記事は下記になりますので、未参照の方は一読することをおすすめします。

GolangでRESTful APIを開発する方法については、以下のセクションで構成されています。

  1. API エンドポイントを設計する。
  2. コード用のフォルダを作成する。
  3. データを作成する。
  4. すべての項目を返すハンドラを記述する。
  5. 新しいアイテムを追加するハンドラを書く。
  6. 特定の項目を返すハンドラを記述する。

前回の記事では、セクション4までをご紹介しました。本記事では、セクション5以降についてご紹介しています。

新しい項目の追加処理

クライアントが/albumsにPOSTリクエストをしたとき、リクエストボディに記述されたアルバムを既存のアルバムデータに追加します。

そのためには、下記の手順を実施します。

  • 新しいアルバムを既存のリストに追加するロジック。
  • POSTリクエストをロジックにルーティングする。

アルバムリストにアルバムデータを追加するコードを追加する。

import文の後のどこかに、以下のコードを貼り付ける。(このコードはファイルの最後が良いのですが、Goは関数を宣言する順番を強制しません)

// postAlbums adds an album from JSON received in the request body.
func postAlbums(c *gin.Context) {
    var newAlbum album

    // Call BindJSON to bind the received JSON to
    // newAlbum.
    if err := c.BindJSON(&newAlbum); err != nil {
        return
    }

    // Add the new album to the slice.
    albums = append(albums, newAlbum)
    c.IndentedJSON(http.StatusCreated, newAlbum)
}


次のように、main関数にrouter.POST関数を含めるように変更します。

func main() {
    router := gin.Default()
    router.GET("/albums", getAlbums)
    router.POST("/albums", postAlbums)

    router.Run("localhost:8080")
}

コードを実行する

最後のセクションでサーバーがまだ動いている場合は、サーバーを停止する。

main.goのあるディレクトリのコマンドラインから、コードを実行する。

go run .

別のコマンドラインウィンドウから、curlを使って実行中のウェブサービスにリクエストを出す。

curl http://localhost:8080/albums \
    --include \
    --header "Content-Type: application/json" \
    --request "POST" \
    --data '{"id": "4","title": "The Modern Sound of Betty Carter","artist": "Betty Carter","price": 49.99}'

下記のような出力になっていれば成功です。

 % curl http://localhost:8080/albums \
    --include \
    --header "Content-Type: application/json" \
    --request "POST" \
    --data '{"id": "4","title": "The Modern Sound of Betty Carter","artist": "Betty Carter","price": 49.99}'

HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
Date: Thu, 22 Jun 2023 12:18:27 GMT
Content-Length: 116

{
    "id": "4",
    "title": "The Modern Sound of Betty Carter",
    "artist": "Betty Carter",
    "price": 49.99
}

前のセクションと同様に、curlを使ってアルバムの全リストを取得し、それを使って新しいアルバムが追加されたことを確認する。

% curl http://localhost:8080/albums  
[
    {
        "id": "1",
        "title": "Blue Train",
        "artist": "John Coltrane",
        "price": 56.99
    },
    {
        "id": "2",
        "title": "Jeru",
        "artist": "Gerry Mulligan",
        "price": 17.99
    },
    {
        "id": "3",
        "title": "Sarah Vaughan and Clifford Brown",
        "artist": "Sarah Vaughan",
        "price": 39.99
    },
    {
        "id": "4",
        "title": "The Modern Sound of Betty Carter",
        "artist": "Betty Carter",
        "price": 49.99
    }
]                                                                                                                                       

特定の項目を返す処理

クライアントがGET /albums/[id]というリクエストをしたとき、IDがidパス・パラメータと一致するアルバムを返すAPIを追加します。

そのために、下記のことをします。

  • リクエストされたアルバムを取得するロジックを追加する。
  • パスをロジックにマップします。

前のセクションで追加したpostAlbums関数の下に、特定のアルバムを取得するために以下のコードを貼り付けます。

このgetAlbumByID関数は、リクエストパスのIDを抽出し、一致するアルバムを探します。

// getAlbumByID locates the album whose ID value matches the id
// parameter sent by the client, then returns that album as a response.
func getAlbumByID(c *gin.Context) {
    id := c.Param("id")

    // Loop over the list of albums, looking for
    // an album whose ID value matches the parameter.
    for _, a := range albums {
        if a.ID == id {
            c.IndentedJSON(http.StatusOK, a)
            return
        }
    }
    c.IndentedJSON(http.StatusNotFound, gin.H{"message": "album not found"})
}

最後に、次の例に示すように、mainを変更して、router.GETの新しい呼び出しを含むようにします。ここで、パスは/albums/:idになります。

func main() {
    router := gin.Default()
    router.GET("/albums", getAlbums)
    router.GET("/albums/:id", getAlbumByID)
    router.POST("/albums", postAlbums)

    router.Run("localhost:8080")
}

最後のセクションでサーバーがまだ動いている場合は、サーバーを停止する。

main.goのあるディレクトリのコマンドラインから、サーバーを起動するコードを実行してください。

go run .

別のコマンドラインウィンドウから、curlを使って実行中のウェブサービスにリクエストを出す。

curl http://localhost:8080/albums/2

コマンドは、使用したIDのアルバムのJSONを表示するはずです。

% curl http://localhost:8080/albums/2
{
    "id": "2",
    "title": "Jeru",
    "artist": "Gerry Mulligan",
    "price": 17.99
}

アルバムが見つからなかった場合は、エラーメッセージとともにJSONが表示されます。

% curl http://localhost:8080/albums/22
{
    "message": "album not found"
}

解説

postAlbums メソッド

このコードは、Ginフレームワークを使用してHTTP POSTリクエストを処理するハンドラ関数です。リクエストボディで受け取ったJSON形式のアルバムデータを解析し、アルバムを追加します。

以下がコードの解説です:

  1. postAlbums関数は、gin.Contextオブジェクトを引数として受け取ります。これは、HTTPリクエストとレスポンスのコンテキストを表します。
  2. newAlbumという名前のalbum型の変数を宣言します。この変数は、リクエストボディから受け取ったJSONデータを格納するために使用されます。album型は、おそらくこのコードの別の場所で定義されていると思われます。
  3. c.BindJSON(&newAlbum)を呼び出して、受け取ったJSONデータをnewAlbumにバインドします。これにより、JSONデータがnewAlbumのフィールドにマッピングされます。エラーが発生した場合は、処理を終了して関数から戻ります。
  4. 新しいアルバムをスライスalbumsに追加します。append関数を使用して、albumsスライスにnewAlbumを追加します。
  5. c.IndentedJSON(http.StatusCreated, newAlbum)を呼び出して、レスポンスをJSON形式で返します。http.StatusCreatedは、HTTPステータスコード201(Created)を表します。newAlbumは、追加されたアルバムのデータです。

このコードは、HTTP POSTリクエストを受け取り、リクエストボディで受け取ったJSONデータを解析し、アルバムを追加してレスポンスとして返す役割を持っています。

getAlbumByID メソッド

このコードは、Ginフレームワークを使用してHTTP GETリクエストを処理するハンドラ関数です。クライアントから送信されたIDパラメータと一致するID値を持つアルバムを探し、そのアルバムをレスポンスとして返します。

以下がコードの解説です:

  1. getAlbumByID関数は、gin.Contextオブジェクトを引数として受け取ります。これは、HTTPリクエストとレスポンスのコンテキストを表します。
  2. id := c.Param("id")を使用して、クライアントから送信されたIDパラメータを取得します。Paramメソッドを使用することで、URLのパスに含まれるパラメータを取得できます。ここでは、パスの一部としてidパラメータが指定されていることが想定されています。
  3. スライスalbumsの各アルバムに対してループを実行し、パラメータと一致するID値を持つアルバムを探します。
  4. ループ内で、現在のアルバムを表す変数aのID値がパラメータのIDと一致するかをチェックします。一致する場合、c.IndentedJSON(http.StatusOK, a)を呼び出して、そのアルバムをJSON形式でレスポンスとして返します。http.StatusOKは、HTTPステータスコード200(OK)を表します。
  5. アルバムが見つからない場合、c.IndentedJSON(http.StatusNotFound, gin.H{"message": "album not found"})を呼び出して、エラーメッセージを含むJSON形式のレスポンスを返します。http.StatusNotFoundは、HTTPステータスコード404(Not Found)を表します。

このコードは、HTTP GETリクエストを受け取り、指定されたIDパラメータと一致するアルバムを探し、そのアルバムをレスポンスとして返す役割を持っています。また、アルバムが見つからない場合はエラーメッセージを含むレスポンスを返します。

おわりに

前回と今回の記事では、GoとGinを使ってシンプルなRESTfulウェブサービスを書きました。

本記事で使用したコードは下記のリポジトリにあります。


Ginの詳細については、Gin Web FrameworkパッケージのドキュメントまたはGin Web Frameworkのドキュメントを参照してください。

Golangが初めての方は、Effective Go と How to write Go codeに役立つベストプラクティスが記載されています。

また、Go ツアーというGolang の基礎をステップバイステップで学べる入門サイトもあります。

よっしー
よっしー

何か質問や相談があれば、遠慮なくコメントしてください。また、エンジニア案件についても、いつでも相談にのっていますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました