ソースコードから理解する技術-UnderSourceCode

手を動かす(プログラムを組む)ことで技術を理解するブログ

FirestoreにGolangでデータを登録してみる

はじめに

GoogleのFirebaseを初めて触ってみました。
今回はFirestoreにGolangでデータを登録・参照してみました。
以下、その時のメモと、作ったソースです。

手順について

まずはGoogleのアカウントが必要なので、あらかじめ作っておく必要があります。
基本的な手順は、以下の公式ドキュメントの通りとなります。

https://firebase.google.com/docs/firestore/quickstart?authuser=0

1. プロジェクト、データベースの作成

上記の公式ドキュメントのリンクからFirebaseコンソールを開き、プロジェクトを作成します。
次にデータベースを作りますが、この時にルールは厳しい方(名前はメモするのを忘れた)を選択します。
(外部からアクセスできない設定にします。後で変更します。)

2. データベースのルール変更

先の設定ではプログラムからはアクセスできないので変更します。
今回はユーザIDが正しい場合のみアクセスできるようにしました。
Firebaseコンソールの「ルール」タブを開き、権限設定を以下のように変更します。

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      match /users/{userId} {
        allow read, write: if request.auth.uid == userId;
      }
    }
  }
}

「allow read, write: if request.auth.uid == userId;」のifの右で
read・writeを許可する条件としてユーザIDが一致することを定義しています。

3. SDKの取得

FirebaseのSDKがない場合、go getで取得する必要があります。
この時、-uオプションをつけないで実行すると以下のようなエラーとなりました。

# go.opencensus.io/plugin/ocgrpc
../../../go.opencensus.io/plugin/ocgrpc/trace_common.go:43:9: undefined: metadata.AppendToOutgoingContext

これを回避するには-uオプションをつけ、以下のようにgo getを実行しました。

go get -u firebase.google.com/go

4. サービスアカウントの秘密鍵を取得

サービスアカウントの秘密鍵を取得します。
取得する場所が分かりにくかったのですが、プロジェクトに紐づいたアカウントを取得するため、以下の箇所から取得しました。

  • 画面左上の「Project Overview」から「プロジェクトの設定」を選択
  • 「サービス アカウント」タグを選択
  • 「新しい秘密鍵の生成」ボタンを押下

秘密鍵の形式はjsonを選択し、ローカルに保存して共有しないようにします。
またここで各プログラム言語ごとにFirebaseアプリケーションのオブジェクトを作るサンプルソースが表示されるので、これもメモっておきます。

5. プログラムの作成

上記でメモったサンプルソースと、公式サイトのソースを元に、今回は以下のようなプログラムを作成しました。

package main

import (
	"fmt"
	"log"
	"os"

	"golang.org/x/net/context"

	firebase "firebase.google.com/go"

	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
)

func main() {
	fmt.Println("----- main start -----")

	jsonPath := os.Getenv("FIREBASE_JSON_PATH")

	opt := option.WithCredentialsFile(jsonPath)
	ctx := context.Background()
	app, err := firebase.NewApp(context.Background(), nil, opt)
	if err != nil {
		log.Fatalln(err)
	}

	client, err := app.Firestore(ctx)
	if err != nil {
		log.Fatalln(err)
	}
	defer client.Close()

	// create
	_, _, err = client.Collection("users").Add(ctx, map[string]interface{}{
		"first": "Ada",
		"last":  "Lovelace",
		"born":  1815,
	})
	if err != nil {
		log.Fatalf("Failed adding alovelace: %v", err)
	}

	// create
	_, _, err = client.Collection("users").Add(ctx, map[string]interface{}{
		"first":  "Alan",
		"middle": "Mathison",
		"last":   "Turing",
		"born":   1912,
	})
	if err != nil {
		log.Fatalf("Failed adding aturing: %v", err)
	}

	// reference
	iter := client.Collection("users").Documents(ctx)
	for {
		doc, err := iter.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			log.Fatalf("Failed to iterate: %v", err)
		}
		fmt.Println(doc.Data())
	}

	fmt.Println("----- main end -----")
}

秘密鍵jsonのパスを環境変数「FIREBASE_JSON_PATH」として保持した以外は、各サンプルソースそのままとなっています。
(一部のコメント、fmt.Printlnを除く。)

これを実行すると以下のようにターミナルに出力されます。

----- main start -----
map[last:Turing first:Alan born:1912 middle:Mathison]
map[first:Ada born:1815 last:Lovelace]
----- main end -----

Firebaseコンソールのデータベースを確認しても、プログラムにて登録したデータが表示されるはずです。

最後に、今回作成したソースは以下になります。
GitHub - SrcHndWng/go-learning-firestore