2022年3月9日水曜日

GAEのGo言語でuser APIが機能しない件

Goを使ってGAEのアプリケーションを作り始めたけど、管理画面を作る段階でいきなり行き詰まった。

user APIがあるんだけど、それがどうしても機能してくれなくて、LoginURLやLogoutURLが返ってこないんです。

検索して出てくるコードのまま書いてるんだけど、全然動いてくれないし、それ以上の情報が出てこない。

やむを得ず、Googleの有料サポートに申し込んで教えてもらった。

そのGCPの有料サポートが超絶素晴らしかったという内容はこちらの記事を読んでください。

どうしても動かなかったのは以下の部分。user APIを使う部分が全て返ってきてくれないんです。


import (
    ...
    "github.com/gorilla/mux"
    "google.golang.org/appengine/v2"
    "google.golang.org/appengine/v2/user"
    ...
)

func Entry(w http.ResponseWriter, r *http.Request) {
    ...
    ctx := appengine.NewContext(r)
    isadmin := user.IsAdmin(ctx)
    loginUrl, err := user.LoginURL(ctx, "/admin/top/")
    logoutUrl, err := user.LogoutURL(ctx, "/")
    ...
}

これを実行すると、エラーは出ないけど、isadmin、loginUrl、logoutUrlの全てが何も返ってこないんです。

同じ問題で悩んでいる人がいるかもしれないので、解決方法を書いておきますので、参考にして下さい。

結論から言うと、問題が発生してたのは、github.com/gorilla/muxです。

これをインポートして、使う場合は最後に1行追加しなければならないんです。

ゴリラマックス(Gorillamux)を使う場合、URLマッピングの部分を以下のように書きます。


import (
    ...
    "github.com/gorilla/mux"
    "net/http"
    ...
)

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/", indexHandler)
    r.HandleFunc("/admin/", admin.Entry)
    http.Handle("/", r)
}

ポイントは、順番にURLマッピングをして、最後にhttp.Handle("/", r)というのを1行書いて、登録してやらないといけないんです。

この1行が抜けてから、何度やってもできなかったんですね。

ということで無事に解決できました。

ちなみにGorillamuxを使わない場合は、このように書きますよね。


import (
    ...
    "github.com/gorilla/mux"
    "net/http"
    ...
)

func main() {
    http.HandleFunc("/", indexHandler)
    http.HandleFunc("/admin/", Entry)
}

こうやって書いた場合には、簡単ですが、Gorillamuxを使わないと複雑なURLマッピングができないので、ゴリラを使っている人は参考にしてください。

ゴリラを使う場合には少し書き方が変わるので注意が必要です。

何か質問があれば、お気軽にコメント下さい。

Google Cloud Plaatformのサポート(スタンダード)での対応に感動した!

今回はGCPのサポートが受けたいという人やスタンダードやエンハンストなどの有料サポートを検討している人に役立つ内容だと思います。

GAEでWebサイトを作ってるんだけど、どうしても分からないところがあったからGCPの有料サポートに入った。

検索して必死で調べて、Stack Overflowを使ってレスポンスもいただいたんだけど、どうしても解決できなかったんです。

GCPの有料サポートは、いくつか種類がある。

種類と価格は以下の通り。

プランによって受けられるサポートが違って、一番安いスタンダードで自分が引っ掛かってる問題をサポートしてもらえるのか不安だった。

そこでまず、Googleの窓口に電話をして、スタンダードでも技術的なサポートをしてもらえるのか確認した。

あまり愛想のよくない感じの担当者が対応してくれて、技術的なサポートも受けられますと教えてくれた。

プランによって大きく違うのは、レスポンスの時間。

スタンダードプランの場合、基本的にレスポンスをもらえるまでに8時間くらいはかかると思っておいた方がいいし、実際多くの場合それくらいの時間がかかる。

で、早速質問してみた。

GCPのサポートは、ケースというものを作って質問をすることになる。

基本的には、全て英語でやりとりしなければならない。

辞書とGoogle翻訳を使いながら、必死で英語で文章を書いてやりとりをした。

自分の英語力がないのもあって、なかなか担当の人が私の言ってることを理解してくれなくて、2回くらい返信をもらったけど解決できなかった。

返信してくれる内容がかなりテクニカルな内容なので、単なる事務の人が対応してくれているわけではなくて、Googleのエンジニアの人が対応してくれてるというのが分かる。

Google App Engineで開発をしてて、Googleのエンジニアに直接教えてもらえるというのは非常にありがたい。

その時点で、嬉しくで感動した。

どうしても、私の言ってることが伝わってなかったみたいで、教えてもらったことを何度も試したけど問題を解決できなかった。

そしたら、Googleのエンジニアの人が、ビデオ会議を使って画面共有して教えてあげると言ってくれた。

めちゃくちゃ嬉しかったけど、私は英語の読み書きはなんとかできるものの、リスニングとスピーキングはかなりやばいレベルなので、一度断った。

でも、Googleのエンジニアの人がチャットでもサポートしてあげるから、やってみようと言ってくれた。

もう本当に涙が出るくらい感動しましたよ。マジで。

しかも、3つくらいスケジュールをくれて、その中なら都合の良い時間帯を選んでくれって言ってくれて、次の日の朝にすぐ予定を入れてくれた。

ビデオ会議では、必死になってGoogle翻訳を使いながらやりとりして、どうしても聞き取れない時は、Chat, please!と言って、チャットでメッセージを送ってもらって頑張った。

画面共有しながら必死で説明したら、ようやく私の言ってることを理解してくれたみたいで、あなたの言ってることが理解できたから後で連絡すると言ってくれた。

その後、数時間後に連絡が来た。

その内容が本当にすごくて、「私が実際にコードを書いて動かしたら、問題なく動いたよ!」っていう内容だった。

しかも、「私が書いてきちんと動いたコードをサンプルとしてあげるから、これで1つずつ確実に動くか確認しながらやってみてね!」って言ってサンプルコードまでくれたんです。

で、そのサンプルコードを見ながらやったら、何とやりたかったことができるようになって一瞬で問題が解決した!

一番安い月額29ドルのスタンダードサポートなのに、まさかGoogleのエンジニアさんが、ここまで親身になって、丁寧に、何度もできるまで対応してくれるなんて夢にも思ってなかった。

マジで超感動した!

今まで20年近く、Googleの検索エンジンで集客して、Googleアドセンスで稼がせてもらって、Googleが大好きで本当に感謝してたけど、その思いがさらに増した。

今なんて、Googleの作ったGoを使って、GoogleのサーバーであるGoogle App Engineを使ってWebアプリを作って、Googleの検索エンジンで集客して、Googleアドセンスで稼ぐっていうことをやってるんだから、Googleさんには本当に感謝しかない。

昔、Googleのオフィスが六本木ヒルズにあった時に、アドセンスのセミナーに招待していただいて行ったことがある。

その時に、Googleの人と少し話をしたけど、感謝の思いを伝えるのを忘れた。

次にGoogleの人と会う機会があったら、絶対に「ありがとう!」と言いたい。

このブログをGoogleの人が見てるとは思えないけど、このブログを通じて、「Googleさん、大好き!Googleさん、ありがとう!」と言わせていただきます。

名前は書けないけど、対応してくれたGoogleのエンジニアさんの助けがなかったら、絶対に解決できなかったし、もし解決できなかったら諦めてたと思う。

問題の原因を特定することができたし、これでやっと先に進むことができるようになりました。

有料のサポートだけど、これは十分に価値があるし、むしろ安過ぎるくらいの価格だと思うから本当にありがたい。

良心的な価格設定で、私たち利用者を最大限手助けしようっていう意志が感じられる。

絶対にいいWebアプリを作って、成功させて、GAEの料金をたくさん払えるようになって恩返ししたいと思う。

長々と書いたけど、結局何が言いたいのかというと、「GCPのサポートは最高!!!」という事です。

私みたいな英語力も技術力もない人間に対しても、全く偉そうにせず、親身に、丁寧に対応してくれます。

GCPやGAEのサポートを受けたいと考えてる人には本当におすすめです。

まずはスタンダードに今すぐ入りましょう。そして、それでも解決できなくて、もっと高度なサポートを受けたい場合には、エンハンストにアップグレードすればいいでしょう。

ちなみに検索すると、ブロンズ、シルバー、ゴールド、プラチナというサポートシステムが出てきますが、これは古い情報なんだと思います。

2022年3月8日火曜日

Goのfor文とcontinue、break

今回はGoのfor文の書き方です。

配列を順番に取り出したらい、ループを回すのに使うことが多いです。

こちらも言葉で説明するよりもコードを見た方が早いと思いますので、以下のコードを書いて実行しましょう。

[main.go]


package main

import "fmt"

func main() {
	for i := 0; i < 10; i++ {
		fmt.Println(i)
	}
}

これを実行すると、以下のように出力されます。


0
1
2
3
4
5
6
7
8
9

iが初期値で最初に0を代入しています。

次に条件判定で、iの値が10未満となるまでループを回すように設定しています。

そして、最後にループを1回実行するたびにiの値を1ずつ増やしています。

書き方さえ覚えてしまえば、そんなに難しくないですよね。

次にcontinueの使い方の説明です。

まずは、以下のコードを書いて実行してみましょう。

[main.go]


package main

import "fmt"

func main() {
	for i := 0; i < 10; i++ {
		if i == 5 {
			continue
		}
		fmt.Println(i)
	}
}

これを実行すると、以下のように出力されます。


0
1
2
3
4
6
7
8
9

ご覧のように5だけが出力されません。

これは、ある条件にマッチした時に、continueを使うと、その時の処理がスキップされるからです。

先ほどのコードで言えば、iの値が5の時にcontinueを実行していますので、5がスキップされるのです。

次にbreakの使い方の解説です。

以下のコードを書いて実行してみましょう。

[main.go]


package main

import "fmt"

func main() {
	for i := 0; i < 10; i++ {
		if i == 5 {
			break
		}
		fmt.Println(i)
	}
}

これを実行すると、以下のように出力されます。


0
1
2
3
4

これを見たらすぐに分かると思いますが、continueが実行されると、そこでループから抜けて処理が終了します。

continueの場合は、スキップして処理が継続されますが、continueの場合はそこでループが終了となります。

for、continue、breakを使えば、いろんな処理を実行することができるので、必ずマスターしましょう。

2022年1月20日木曜日

Goのif文の書き方

今回はGoのif文の書き方です。

if文というのは条件によって分岐させる処理のことです。

言葉で説明するよりもコードを見たら一目瞭然なので、以下のコードを書いて実行しましょう。

package main

import "fmt"

func main() {
	num1 := 3
	if num1 == 1 {
		fmt.Println("num1 is 1")
	} else if num1 == 2 {
		fmt.Println("num1 is not 2")
	} else {
		fmt.Println("num1 is not 1 and 2")
	}

	num2, num3 := 3, 4
	if num2 == 3 && num3 == 4 {
		fmt.Println("num2 is 3, num3 is 4")
	}

	if num2 == 3 || num3 == 4 {
		fmt.Println("num2 is 3 or num3 is 4")
	}

}

これを見たらもう分かりますよね。

説明はいらないと思います。

num1、num2、num3の値を変えて実行したら何をしているのかがすぐに分かると思います。

&&はかつ(and)の意味で、||はまたは(or)の意味です。

複数の条件で分岐させたい時に使えます。

Goの関数の宣言と使い方

今回は、Goの関数について書きます。

関数が使えるようになるとスッキリしたコードが書けるようになります。

言葉で説明するよりも、コードを見た方が分かりやすいと思うので、以下のコードを書いて実行してみましょう。

3と5の2つを引数として渡して、その合計を表示します。

package main

import "fmt"

func add_num(x int, y int) int {
	return x + y
}

func main() {
	answer := add_num(3, 5)
	fmt.Println(answer)
}

これを実行すると3+5で8と表示されます。

まず、関数を宣言するためにfuncとし、その後ろに好きな関数名を書きます。

関数名は自由に書く事ができますが、関数名を見たらすぐにその関数が何をするものなのかというのが分かるような名前にするのが良いです。

関数名の後ろに()を書き、その中に引数を型と合わせて書きます。

さらに、その後ろに返ってくるものの型を書きます。

宣言した関数を使う時には、関数名の後ろに()を付けて、その括弧の中に引数をカンマで区切って書きます。

最初は、型を書いたりと少しややこしく感じるかもしれませんが、慣れてくるとそんなに難しくありません。

次に、変数に関数を入れるというやり方で書いてみましょう。

これも先にコードを書いて実行して下さい。

package main

import "fmt"

func main() {
	f := func(x int, y int) {
		fmt.Println(x + y)
	}
	f(3, 5)
}

これもさっきと同じで8と表示されます。

さっきと違うのは、関数名を書いて宣言するのではなく、関数をそのまま変数に代入しているところです。

最初は、このような書き方は使わないと思いますが、一応覚えておきましょう。

最後に、もっとシンプルな書き方です。

package main

import "fmt"

func main() {
	func(x int, y int) {
		fmt.Println(x + y)
	}(3, 5)
}

これを実行すれば分かると思うのですが、やはり8と表示されます。

関数を変数名に代入すらせずに、そのまま実行しているのです。

Goの関数は書き方が複数あるので、最初は難しく感じるかもしれません。

慣れるまでは、基本的な書き方で十分なので、慣れたら別の書き方も練習していきましょう。

2022年1月18日火曜日

Goの数値型と四則演算

今回は Goの数値型について説明します。

Goにはたくさんの数値型があります。

例えば、uint8、int8、float32、complex64などがあります。

ただ、最初の段階では整数型のintと浮動小数点数のfloat64だけ覚えておけば十分です。

他のものについては、実際にアプリの開発などを始めて使う必要が出てきた時に調べれば十分でしょう。

まず、最初は簡単な基本的なところだけを理解しながら最後まで進みましょう。

そして、最後まで終わったら、また最初に戻って少しずつ深めて勉強していくと効率が良いです。

では、数値型を使って四則演算をして見ましょう。

以下のコードを書いて実行してみましょう。

package main

import "fmt"

func main() {
	fmt.Println("1 + 1 =", 1+1)
	fmt.Println("10 -2 =", 10-2)
	fmt.Println("3 * 3 =", 3*3)
	fmt.Println("9 / 3 =", 9/3)
	fmt.Println("10 % 3 = ", 10%3)
	fmt.Println("15 / 6 =", 15/6)
	fmt.Println("15 / 6.0 =", 15/6.0)
}

これを実行すると、以下のように出力されます。

1 + 1 = 2
10 -2 = 8
3 * 3 = 9
9 / 3 = 3
10 % 3 =  1
15 / 6 = 2
15 / 6.0 = 2.5

別に難しくないですよね。

注意すべき点としては、最後の2つです。

単に15/6と書けば、小数点以下は切り捨てられてしまいます。

小数点まできちんと出力したければ、どちらかを浮動小数点数にする必要があります。

掛け算は*、割り算は/、余りは%ですので覚えておきましょう。

他にも++という書き方や+=という書き方などもありますが、それはもう少しGoの勉強が進んでからで大丈夫かと思います。

これでGoを使って簡単な計算をすることができるようになりましたね。

Go言語の定数const

変数の次は定数です。

変数は宣言して値を代入した後に、別の値をさらに代入して値をどんどん変えることができます。

これに対して、定数は、一度値を代入したら、その後は値を変更することができません。

Goでは定数を宣言するのにconstを使います。

例えば、以下のように書きます。

package main

import "fmt"

func main() {
	const Name = "Uber Go"
	fmt.Println(Name)
}

定数Nameの最初のNは大文字です。これはまた後ほど詳しく解説しますので、今は気にしなくても大丈夫です。

そして、この後に以下のようにしてNameに別の値を代入しようとするとエラーが出ます。

package main

import "fmt"

func main() {
	const Name = "Uber Go"
	fmt.Println(Name)
	Name = "Run"
}

これを実行すると以下のようなエラーが出てNameには別の値を代入できませんということが表示されます。

./lesson.go:8:7: cannot assign to Name (declared const)

これがGoの定数constの使い方です。

定数には、後ほど変更しない値を入れる時に使うようにしましょう。

GAEのGo言語でuser APIが機能しない件

Goを使ってGAEのアプリケーションを作り始めたけど、管理画面を作る段階でいきなり行き詰まった。 user APIがあるんだけど、それがどうしても機能してくれなくて、LoginURLやLogoutURLが返ってこないんです。 検索して出てくるコードのまま書いてるんだけど、全...