GoでFirebaseをいじいじする
▷ はじめに
Golangを使ってFirebaseをいじいじしてみたので、「こういうとこで詰まったよ〜」っていうのと、 「こんなことできたよ〜」っていうのを書いていきます📝
コードが汚かったり、変なことを言っても初心者なので許してちょんまげ!!!
▷ Let's 下準備 📦
今回はGolang自体の環境構築自体は省略いたします。 環境構築がまだの方はこちらから
また、Firebaseのプロジェクト作成も省略いたします。 環境構築がまだの方はこちら
▼ Modulesのインストール!
まずは必要なModulesを導入していきます。 こちらのコマンドでFirebase Admin SDK を追加します。
main.gogo get firebase.google.com/go
▼ 秘密鍵の作成!
ついでに秘密鍵🔑も作成しておきましょう! 「歯車マーク > ユーザーと権限 > サービスアカウント」の順番で進んでいくと、以下のような画面になると思います。
青色の「新しい秘密鍵を作成」ボタンを押すと.jsonファイル
をダウンロードできますので、それを開発ディレクトリに貼り付けましょう!
Admin SDK 構成スニペット
がが必要であればGo
を選択し、コピペしておきましょう!
今回はrootにserviceAccountKey.json
を生成し、そこに貼り付けます。
(.ignore
で非公開設定にするのを忘れないように⚠️)
今回はこんな感じのディレクトリ構成で開発をはじめました!
▼ 初期化
ここまで来たらちゃんと導入に成功しているかをチェックします✅
今回は下記のコードでチェックしました!
何も問題なければターミナルでsuccess!!
が表示されるはずです。
package main import ( "context" "fmt" firebase "firebase.google.com/go" "google.golang.org/api/option" ) func main() { ctx := context.Background() sa := option.WithCredentialsFile("serviceAccountKey.json") app, err := firebase.NewApp(ctx, nil, sa) if err != nil { fmt.Println("接続エラー。") } cilent, firestoreErr := app.Firestore(ctx) if err != nil { fmt.Println("error getting Auth client: \n", firestoreErr) } fmt.Println(client) fmt.Println("success!!") }
▷ 開発開始 💻
Firebaseを触るのに必要最低限の準備が(多分)できたので、早速それっぽいことをやっていきましょう😏
こちらのコードを、先ほど書いたコードの下に書くと…
// スライス(配列っぽいやつ)の宣言 var initialTechnology []string // スライス(配列っぽいやつ)に値を追加する technology := append(initialTechnology, "Next") // Firestoreにデータを追加する _, err = client.Collection("users").Doc(userInfo.ID).Set(ctx, map[string]interface{} { "id": "sampleId", "userName": "go master", "email": "go.master@exsample.com", "technology": technology, })
何ということでしょう! こんなにも容易くFirestoreにデータを保存することができました👏
あとは自由に保存するデータ構造や値をいじったり、受け渡す値を動的にしたりなど、いろいろ楽しんでみましょう!
▷ 詰まったところ 🚨
今回開発する上でGoが嫌いになるくらいに詰まってしまった部分を列挙しておきます。 この解決方法が正しかったかもわかりません。
動けばよかろうなのだーーーーー!
▼ Arrayがむずかちい
私はこれまでJavaScript
しか触ってこなかったので、それ以外の言語がについての知見が皆無なのですが…
Go版「Array」みたいなのがめっちゃわかりにくいかった🥺
GoではArray
がarray
と slice
ってのに別れるっぽい。違いはわかりませんでした。
でも、ここら辺を曖昧なまま進めたことで悲劇は起きてしまいました…。
▼ Arrayの要素数が固定だと…?
それっぽくgolang array
って調べると当然ながらGo版「Array」が検索に引っかかるんですが、どうやら「要素数が固定的」なものらしい。
じゃあ、要素を追加したり、削除したりできないじゃんって思いました? 動的な値の時ってどうすんのよって思いました?!
僕も全くおんなじこと思いました。 しかもめっちゃエラー吐くんですよね(絶望)。
▼ 救世主!slice!
ということで、ここで登場するのがslice
です。
なんと宣言時に要素数を書かないだけでsliceになるらしい。
// 要素数を指定しないだけで slice になる var technology []string // 要素数を指定すると array になる var technology [3]string
sliceを宣言することで、要素の追加が可能になります!
要素を追加したい時はappend()
を使用します。
// append()は新しいsliceを返す // JavaScriptのmap()みたいなものかな?多分 newTechnology = append(technology, 追加したい要素)
▼ 問題児!slice!
最後の問題もやはり、配列で起こってしまいました…。
Firestoreからデータを取得し、配列操作をしたいな〜と思っていた時です。
// Firestoreからデータを取得 snapshot, firestoreErr := client.Collection("users").Doc(userInfo.ID).Get(ctx) // エラーチェック if firestoreErr != nil { fmt.Println("Failed adding alovelace:", firestoreErr) } // 取得した配列に、新しい要素を追加したい…! var res = snapthot.data()["technology"] technology := append(res, "Golang") fmt.Println(technology)
なんと!!この書き方だと配列操作ができないというのです。
原因はres
がinterface{}型
(空インターフェース)になってしまうことでした。
▼ 究極奥義!型アサーション!
本来の[]string型
に戻すためには型アサーションなるものを行う必要があるそうです。JSでいう型チェック的なものでしょう。多分。
ということで、オラオラ、配列になりやがれーっと型アサーション👿
res, state := snapthot.data()["technology"].([]string);
ですが、これでもうまくいきませんでした。 どんなエラーが出たかは忘れてしまいましたが、とにかくうまくいかなかったのです。
うまくいってるんならこっから先は無視してください。それはそれでバンザイ🙌
▼ 困ったらとりあえず型変換!
このエラーに躓き、はや数時間たった深夜。 とある記事に出会うことで運命の歯車⚙が回り始めちゃいました!
FirestoreとGoのデータ型変換の関係という記事に出会い、「Firestore から Go のデータ型変換」という部分を見ると、配列(Arrays) → []interface{}
と書かれてあるではありませんか…!
それに従って以下のように書き直してみると、これまでのエラーが嘘かのように動き始めました👏 ありがとう、Golang!最高だ!
// 取得した配列に、新しい要素を追加したい…! res, state := snapthot.data()["technology"].([]interface{}); technology := append(res, "Golang") fmt.Println(technology)
▷ おわりに
っていう感じで、初めてのサーバー言語の開発はエラーばっかりでした。 (のちにチュートリアルを見返したら、ちゃんと説明されてありました😇)
他にもたくさん詰まったところはありましたが、 何とかあってプロダクトを完成させることができました👏
せっかくなので覗いてみてください! ハックちゅう for Slack Bot
目次