• トップ
  • ブログ一覧
  • 【第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)を習得したい!~笹川先生(株)ライトコードでモバイルアプリケーション開発をしている笹川...

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    笹川(エンジニア)
    笹川(エンジニア)
    Show more...

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background