• トップ
  • ブログ一覧
  • 【第5回】Go言語(Golang)入門~REST API実装編~
  • 【第5回】Go言語(Golang)入門~REST API実装編~

    笹川(エンジニア)笹川(エンジニア)
    2019.10.09

    IT技術

    第5回~Go言語(Golang)入門~

    秋山笹川先生

    (株)ライトコードの笹川(ささがわ)です!

    前回は、RESR APIを構築するための機能を実装しました。

    今回は、POSTで受け取った値をFirestoreへ追加し、追加されたデータをレスポンスとして返す実装をしてみたいと思います。

    前回の記事はこちら

    featureImg2019.10.02【第4回】Go言語(Golang)入門~REST API環境構築編~第4回~Go言語(Golang)入門~笹川先生(株)ライトコードの笹川(ささがわ)です今回も、Go言語(Golang)...

    Firestoreへのデータ追加の実装を作ってみよう!

    まずは、Firebaseの初期化処理を実装しようと思います。

    1func firebaseInit(ctx context.Context) (*firestore.Client, error) {
    2    // Use a service account
    3    sa := option.WithCredentialsFile("path/to/serviceAccount.json")
    4    app, err := firebase.NewApp(ctx, nil, sa)
    5    if err != nil {
    6        log.Fatalln(err)
    7        return nil, err
    8    }
    9
    10    client, err := app.Firestore(ctx)
    11    if err != nil {
    12        log.Fatalln(err)
    13        return nil, err
    14    }
    15
    16    return client, nil
    17}

    前回のFirestoreでのデータ操作をした際の記述に対して、戻り値を用意してます。

    初期化処理は共通処理となるので、メソッド化しておいたほうが効率が良さそうです。

    初期化処理だけで実行をしても意味がないので、このまま、データを追加する処理をしてからclientをクローズするまでを実装します。

    Firestoreへのデータ追加処理

    1func dataAdd(name string, age string, address string) error {
    2    ctx := context.Background()
    3    client, err := firebaseInit(ctx)
    4    if err != nil {
    5        log.Fatal(err)
    6    }
    7
    8    // データ追加
    9    _, err = client.Collection("users").Doc(name).Set(ctx, map[string]interface{}{
    10        "age":     age,
    11        "address": address,
    12    })
    13    if err != nil {
    14        log.Fatalf("Failed adding alovelace: %v", err)
    15    }
    16
    17    // 切断
    18    defer client.Close()
    19
    20    // エラーなしは成功
    21    return err
    22}

    Firestoreへのデータ追加処理は、これで完了です。

    それでは、リクエストを受け取って、Json をパースして、Firestore へのデータ追加処理を呼び出してみましょう!

    1type User struct {
    2    Name    string `json:"name"`
    3    Age     string `json:"age"`
    4    Address string `json:"address"`
    5}
    6
    7func main() {
    8    e := echo.New()
    9    e.POST("/users", addUser)
    10    e.Logger.Fatal(e.Start(":1323"))
    11}
    12
    13func addUser(c echo.Context) error {
    14    u := new(User)
    15    if error := c.Bind(u); error != nil {
    16        return error
    17    }
    18    // データ追加呼び出し
    19    if error := dataAdd(u.Name, u.Age, u.Address); error != nil {
    20        return error
    21    }
    22
    23    return c.JSON(http.StatusOK, u)
    24}

    これで実行してみます。

    実行

    リクエストのヘッダーに Content-Type: application/json  を入れて、下記の Json を body にセットしてからリクエストしてみましょう!

    1{
    2    "name": "test1",
    3    "age": "18",
    4    "address": "kanda"
    5}

    curl だと下記のようなコマンドです。

    1curl -X POST \
    2  http://localhost:1323/users \
    3  -H 'Content-Type: application/json' \
    4  -d '{
    5	"name": "test1",
    6	"age": "18",
    7	"address": "kanda"
    8}'

    今の実装だと追加に失敗しない限りは、リクエストの body に入れた Json を返すようにしています。

    笹川は、Postman を利用して実行してみました。

    無事に成功です!

    データを追加成功のレスポンスとしてFirestoreのデータを返してみよう!

    データ追加のあとに、データ読み取りの処理を入れて、Json で返します。

    実装

    それでは、実装してみましょう!

    1// Users はユーザー情報の配列
    2type Users *[]User
    3
    4func dataAdd(name string, age string, address string) ([]*User, error) {
    5    ctx := context.Background()
    6    client, err := firebaseInit(ctx)
    7    if err != nil {
    8        log.Fatal(err)
    9    }
    10
    11    // データ追加
    12    _, err = client.Collection("users").Doc(name).Set(ctx, map[string]interface{}{
    13        "age":     age,
    14        "address": address,
    15    })
    16    if err != nil {
    17        log.Fatalf("Failed adding alovelace: %v", err)
    18    }
    19    // データ読み込み
    20    allData := client.Collection("users").Documents(ctx)
    21    // 全ドキュメント取得
    22    docs, err := allData.GetAll()
    23    if err != nil {
    24        log.Fatalf("Failed adding getAll: %v", err)
    25    }
    26    // 配列の初期化
    27    users := make([]*User, 0)
    28    for _, doc := range docs {
    29        // 構造体の初期化
    30        u := new(User)
    31        // 構造体にFirestoreのデータをセット
    32        mapToStruct(doc.Data(), &u)
    33        // ドキュメント名を取得してnameにセット
    34        u.Name = doc.Ref.ID
    35        // 配列に構造体をセット
    36        users = append(users, u)
    37    }
    38
    39    // 切断
    40    defer client.Close()
    41
    42    // 成功していればusersに値が、失敗の場合はerrに値が入る
    43    return users, err
    44}
    45
    46// map -> 構造体の変換
    47func mapToStruct(m map[string]interface{}, val interface{}) error {
    48    tmp, err := json.Marshal(m)
    49    if err != nil {
    50        return err
    51    }
    52    err = json.Unmarshal(tmp, val)
    53    if err != nil {
    54        return err
    55    }
    56    return nil
    57}

    想定よりも複雑な処理になりました。

    データを読み取る実装自体は、以前の記事でも実装したので説明を割愛します。

    今回のつまづきポイントは、Firestoreから受け取った値がmap型であり、それをJson形式で返すために試行錯誤した点です。

    確認

    追加処理を実装した際に test1 のユーザーは追加済みなので、test2 のユーザーを追加して確認してみます。

    curl だと下記のリクエストで確認できます。

    1curl -X POST \
    2  http://localhost:1323/users \
    3  -H 'Content-Type: application/json' \
    4  -d '{
    5	"name": "test2",
    6	"age": "28",
    7	"address": "chiba"
    8}'

    レスポンスは、test1test2 の情報が下記のように配列で戻ってきたら成功です!

    1[
    2    {
    3        "name": "test1",
    4        "age": "18",
    5        "address": "kanda"
    6    },
    7    {
    8        "name": "test2",
    9        "age": "28",
    10        "address": "chiba"
    11    }
    12]

    毎度のごとくPostmanで確認してみます。

    無事に成功しました!

    第6回へつづく!

    今回は、REST APIとしてGo言語(Golang)からFirestoreのデータを追加してみました。

    1つ1つの実装は難しくないのですが、組み合わせるとどうしても複雑化していってしまいますね。

    Go言語(Golang)は、パッケージ分割などでフィルや処理を分割できます。

    そのため、整理しながら開発していくのが良いように思います。

    今後は、「実際にデプロイ」してみたり、「Androidアプリ等とのデータのやり取り」をしてみたいなと思います!

    今回作成したgoファイルは、こちらのリポジトリにて管理しております。

    次回の記事はこちら

    featureImg2019.10.17【第6回】Go言語(Golang)入門~Twitter API利用編~第6回~Go言語(Golang)入門~笹川先生(株)ライトコードの笹川(ささがわ)です!先日、Twitterでアンケー...

    オススメのGo入門本

    Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る
    Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る

     

    こちらの記事もオススメ!

    featureImg2020.08.08Go言語 特集知識編人気急上昇中のGo言語(Golang)って何だ?実装編Go言語(Golang)入門...

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...

    第1回の記事はこちら

    featureImg2019.09.13【第1回】Go言語(Golang)入門~環境構築編~第1回~Go言語(Golang)を習得したい!~笹川先生(株)ライトコードでモバイルアプリケーション開発をしている笹川...

    笹川(エンジニア)

    笹川(エンジニア)

    おすすめ記事