【Go】初歩的な出力方法いろいろまとめ【Hello world】
こちらの記事では、Goを使ってコンソールに出力を行う方法について、いくつかまとめてご紹介します。
Hello worldまで
まずは Hello world をコンソールに出力するまで。
main.go
package main import "fmt" func main() { fmt.Println("Hello world!") }
$ go run main.go Hello world!
文字列の連携
mainの関数の第2引数以降に文字列を指定することで、文字列を連結した状態でコンソールに出力ができます。
package main import "fmt" func main() { fmt.Println("Hello world!", "Second Message") }
$ go run lesson.go Hello world! Second Message
他の関数を走らせる
mainのファンクション以外を使用する方法は以下の通り。
main.go
package main import "fmt" func Buzz() { fmt.Println("Buzz") } func main() { Buzz() fmt.Println("Hello world!") }
$ go run lesson.go Buzz Hello world!
初期化後にmain以外の関数を走らせる
基本はpackageに対応した関数が走りますが、その前に関数を走らせるための方法もあります。
main.go
package main import "fmt" func Buzz() { fmt.Println("Buzz") } func main() { Buzz() fmt.Println("Hello world!") } func init() { fmt.Println("init!") }
$ go run lesson.go init! Buzz Hello world!
【Go】godoc fmtでcommand not found
go getでGoDocをインストールした後、
$ godoc fmt
を入力すると command not foundになることが。
コマンドが以下のように変更されたようです。
$ go doc fmt.Printf
【Go】インストール後に go コマンドが not found
GoをPCにインストール後、ターミナルから
$ go
を打つと、 command not found になってしまう。
単純にパスが通っていないだけなので、以下の通りターミナルからコマンドを入力して、パスを通しましょう。
$ export PATH=$PATH:/usr/local/go/bin
【Firebase Functions】Functionsの定期実行の方法
定期的にFirebase Functionsを実行させたいという場合には、Cloud Schedulerを使用できます。
以下のようなファンクションを設定することによって、5分毎に処理が実行されます。
exports.removeMember = functions.pubsub.schedule('every 5 minutes').onRun((context) => { console.log('This will be run every 5 minutes!'); return null; });
('every 5 minutes')の部分はcron.yaml構文というもので、以下のリンクが参考になります。
cron.yaml Reference | App Engine standard environment for Python 2 | Google Cloud
注意点としては、毎回実行毎に$0.10が費用として掛かってくるという点です。
それに基づき、従量課金制の「Blasze」モードでなければCloud Schedulerは使用できません。
Schedule functions | Firebase
【Firebase Functions】指定したドキュメントのフィールドの値を取得する
Firebase Functionsのindex.js内で、指定したドキュメント内の値にアクセスしたい場合があります。
具体的には以下の枠線で囲まれた部分をどのように取得するのか、という話です。
以下のコードを例にとってみてみましょう。
exports.addFanpageMember = functions.firestore .document("fanPages/{fanpageId}") .onCreate(async (snap, context) => { const val = snap.data(); try { await admin .firestore() .collection("fanPages") .doc(context.params.fanpageId) .collection("members") .doc(val.userId) .set({ permission: "pageOwner" }); return; } catch (error) { console.log(error); await snap.ref.set({ error: userFacingMessage(error) }, { merge: true }); console.error(error); console.log(`user: ${context.params.userId}`); } });
重要なのは以下の部分です。
functions.firestore .document("fanPages/{fanpageId}") .onCreate(async (snap, context) => { const val = snap.data();
snapには現時点でのfanPages/{fanpageId}で指定したドキュメント内のデータが入っています。そこで、そのデータを取り出すために「const val = snap.data();」という形で記述しています。
このように書くことで、以下のようにオブジェクト形式でデータが入ります。
{ artistName: 'FunctionsTestファンページの紹介', body: 'FunctionsTestファンページの紹介', category: 'singer', monthlyFee: '12456', pageName: 'FunctionsTestファンページの紹介', userId: 'aE91BXgT8fZaDiikdTRF4dmRzhF2' }
.doc(val.userId)のように書いてあげればuserIdが取得できます。その他も同様に取得できます。
【Firebase Functions】Databaseの固有IDを取得したい
以下の枠に囲われた固有IDを取得したい場合があります。
例えば、指定したIDのドキュメント直下に、さらにコレクションやドキュメントを作成する場合です。
その場合、以下のような書き方で固有IDを取得できます。
exports.addFanpageMember = functions.firestore .document("fanPages/{fanpageId}") // このように書く .onCreate(async (snap, context) => { const val = snap.data(); console.log(val); try { await admin .firestore() .collection("fanPages") .doc(context.params.fanpageId) // このように書く .collection("members") .doc(val.userId) .set({ permission: "pageOwner" }); return; } catch (error) { console.log(error); await snap.ref.set({ error: userFacingMessage(error) }, { merge: true }); console.error(error); console.log(`user: ${context.params.userId}`); } });
重要なのは、以下2点です。
.document("fanPages/{fanpageId}") // このように書く .onCreate(async (snap, context) => {
.doc(context.params.fanpageId) // このように書く
ドキュメントを指定する際に「{fanpageId}」といった書き方をすることで、「context.params.fanpageId」と書いてアクセスが可能となります。
【Next.js】メールフォームをFirebase Functionsで実装
今回は、Next.jsとFirebase Functionsを用いて、お問い合わせフォームを実装していきます。
参考にした記事
作成にあたっては以下の2記事が非常に参考になりました。
Vue.js + Firebase functionsでお問い合わせフォームを作成する - Qiita
[firebase] Cloud Functionsを利用したお問い合わせ機能の実装 [react.js] - Qiita
Firebase側の実装
Firebaseとの接続を行います。
lib/db.js
import firebase from 'firebase/app' import 'firebase/firestore' import "firebase/auth"; let db; try { const config = { apiKey : xxxxxxxxxxxxxxxxxxxx, authDomain : xxxxxxxxxxxxxxxxxxxx, databaseURL : xxxxxxxxxxxxxxxxxxxx, projectId : xxxxxxxxxxxxxxxxxxxx, storageBucket : xxxxxxxxxxxxxxxxxxxx, messagingSenderId: xxxxxxxxxxxxxxxxxxxx, appId : xxxxxxxxxxxxxxxxxxxx }; if (!firebase.apps.length) { firebase.initializeApp(config); } // Firestoreインスタンスを作成 db = firebase.firestore(); } catch (error) { console.log(error); } let auth = firebase.auth(); const firestore = firebase.firestore(); module.exports = { // 本来、initializeAppによる初期化は一度きりのため、 // 初期化の結果のみを切り出してexportする db, auth, firebase, firestore };
Firerbase接続に関して、詳しくは以下をご覧ください。
nekorokkekun.hatenablog.com
Firebase Functionsの設定
ルートディレクトリにfunctionsディレクトリを作成します。
次にメーラーをインストールしましょう。
$ yarn add nodemailer $ yarn install
そして、Firebase Functionsの環境変数に、問い合わせを受信するメールアドレスやパスワード、管理者のメールアドレスを設定しましょう。
$ firebase functions:config:set gmail.email="xxxxxx@gmail.com" gmail.password="xxxxxx" admin.email="xxxxxx@gmail.com"
最後にFirebase Functionsを実装します。
functions/index.js
const nodemailer = require("nodemailer"); const gmailEmail = functions.config().gmail.email; const gmailPassword = functions.config().gmail.password; const adminEmail = functions.config().admin.email; // メールサーバー設定 const mailTransport = nodemailer.createTransport({ service: "gmail", auth: { user: gmailEmail, pass: gmailPassword } }); // 管理者用のメールテンプレート const adminContents = data => { return `以下内容でホームページよりお問い合わせを受けました。 お名前: ${data.name} メールアドレス: ${data.email} 内容: ${data.content} `; }; exports.sendMail = functions.https.onCall((data, context) => { // メール設定 let adminMail = { from: gmailEmail, to: adminEmail, subject: "ホームページお問い合わせ", text: adminContents(data) }; // 管理者へのメール送信 mailTransport.sendMail(adminMail, (err, info) => { if (err) { return console.error(`send failed. ${err}`); } return console.log("send success."); }); });
最後に実装したFirebase FunctionsをFIrebaseにデプロイします。
$ yarn deploy
フロント側の実装
以下の記事からそのままお借りしました。
[firebase] Cloud Functionsを利用したお問い合わせ機能の実装 [react.js] - Qiita
import React, { Component } from 'react'; import TextField from '@material-ui/core/TextField'; import Button from '@material-ui/core/Button' import {firebase} from '../lib/db.js'; require("firebase/functions"); class ContactForm extends Component { constructor(){ super() this.onSubmit = this.onSubmit.bind(this) } onSubmit(e){ e.preventDefault() let data = {} data.name = e.target.name.value data.email = e.target.email.value data.content = e.target.content.value let sendMail = firebase.functions().httpsCallable('sendMail'); sendMail(data) e.target.name.value = "" e.target.email.value = "" e.target.content.value = "" e.target.value = "" } render() { const textFieldStyle = { display: "flex", width: "300px", } const contactForm = { display: "flex", flexDirection: "column", alignItems: "center", marginTop: "100px", } return ( <React.Fragment> <div style={contactForm}> <h2>お問い合わせ</h2> <form onSubmit={this.onSubmit}> <TextField name="name" label="お名前" type="text" required style={textFieldStyle} /> <TextField name="email" label="メールアドレス" type="mail" required style={textFieldStyle} /> <TextField required name="content" label="お問い合わせ内容" multiline rows="8" margin="normal" variant="outlined" style={textFieldStyle} /> <Button variant="contained" color="primary" type="submit" style={textFieldStyle} > 送信 </Button> </form> </div> </React.Fragment> ) } } export default ContactForm
これで実際に、設定したメールアドレスへ問い合わせたメールの内容が届くはずです。
Firebase Functionsにエラーが出る場合
以下のようなエラーが出て悩まされました。
send failed. Error: Invalid login: 534-5.7.14 <https://accounts.google.com/signin/continue?sarp=1&scc=1&plt=xxxxxxxxxxx> Please log in via your web browser and then try again. Learn more at https://support.google.com/mail/answer/78754 h16sm1466164ilq.18 - gsmtp
私の場合は、以下のリンクを踏み、アクセスを有効にすることで、メールが届くようになりました。
accounts.google.com