【第5回】Go言語(Golang)入門~REST API実装編~
IT技術
第5回~Go言語(Golang)入門~
(株)ライトコードの笹川(ささがわ)です!
前回は、RESR APIを構築するための機能を実装しました。
今回は、POSTで受け取った値をFirestoreへ追加し、追加されたデータをレスポンスとして返す実装をしてみたいと思います。
前回の記事はこちら
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}'
レスポンスは、test1 と test2 の情報が下記のように配列で戻ってきたら成功です!
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ファイルは、こちらのリポジトリにて管理しております。
次回の記事はこちら
オススメのGo入門本
こちらの記事もオススメ!
2020.08.08Go言語 特集知識編人気急上昇中のGo言語(Golang)って何だ?実装編Go言語(Golang)入門...
2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...
第1回の記事はこちら
2019.09.13【第1回】Go言語(Golang)入門~環境構築編~第1回~Go言語(Golang)を習得したい!~笹川先生(株)ライトコードでモバイルアプリケーション開発をしている笹川...
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
新潟生まれ新潟育ち本業はモバイルアプリエンジニア。 日々、猫(犬)エンジニアとして活躍中!