GCPを使ってみよう!と思い、Go(フレームワークはgin)を使って動かしていました。
しかし、いざDatastoreに接続しようとすると
not an App Engine contex
のようなエラーがでて動かない…。
調べてみるとこんなissueを発見。
datastoreの接続うまくいかない・・・
— やや (@w10y26) 2019年4月1日
これっぽいエラーなんだけど、appengine.Main()含めても同じエラーでたままだしソースコード辿ってもわからん・・・なんでだhttps://t.co/24bNyypqlk
このissueにはappengineを利用してDatastore等を使う場合はこのappengine.Main()を呼び出さなければならないということが書いてありました。
しかしappengine.Main()を加えてもこのエラーが消えず、苦戦していました。
そして先輩にコードみてもらった結果、Goのhttp周りの挙動をちゃんと追っていなかった・ドキュメント読み不足で動いてませんでした。
教えてくれてありがとうございました(T_T)
原因を下に書きます。
❌書いていたコード
// 自分で定義したrouter r := router() err := r.Run() if err != nil { panic("Can't start server.") } appengine.Main()
⭕動くコード
// 自分で定義したrouterをHandleを使って処理を登録 http.Handle("/", router()) appengine.Main()
動かなかった理由は、ginに実装されているRunメソッドをみてみるとわかる。
// gin.go func (engine *Engine) Run(addr ...string) (err error) { defer func() { debugPrintError(err) }() address := resolveAddress(addr) debugPrint("Listening and serving HTTP on %s\n", address) err = http.ListenAndServe(address, engine) return }
ここでListenAndServeが入っているが、今回はAppengineを使うのでこの部分の動きは不要。
上のコードではr.Run()のところでListenAndServe関数が動いてしまっています。
ということでHandleにhttp.Handleの第二引数に自分で定義したhandlerを登録し、appengine.Main()を呼び出せばok。
ちなみにappengine.Main()の中身はこんな感じ。
// appengine func Main() { MainPath = filepath.Dir(findMainPath()) installHealthChecker(http.DefaultServeMux) port := "8080" if s := os.Getenv("PORT"); s != "" { port = s } host := "" if IsDevAppServer() { host = "127.0.0.1" } if err := http.ListenAndServe(host+":"+port, http.HandlerFunc(handleHTTP)); err != nil { log.Fatalf("http.ListenAndServe: %v", err) } }
ドキュメントちゃんと読んだら載ってますね…。
私は今まで動けばいいやスタンスで色々作っていて、フレームワークを使う際は内部の動きとかを全く理解せずに使ってしまっていました…。
Goなら辿りやすいのでこれからは使うだけじゃなくてもうちょっとソースを読みたいと思います。
そしてGoのhttp周りのメソッド名とか似すぎていて、こんがらがってくるのでこのあたりで読み直した。
journal.lampetty.net
qiita.com
間違ってたら教えてください〜。