GAEやappengineなど表記が揺れててどうもググラビリティが低いので併記してみました。

環境

homebrewでapp engine sdkを入れています。

% brew list |grep app-engine
app-engine-go-64

GAE用のGOPATH設定

普通のgoと違ってPaaSの性質上GAEでは使えない機能がある。そういったライブラリを読み込んでるとコンパイルできないので、普通のgoとGAEではGOPATHの設定を変える必要がある。ややこしい。

GAE用のGOPATH設定はいくら調べてみてもこれで決まりというのがわからなかった。いくつかある中で、未設定ならばsdk内のデフォルトが使われるようなのでdirenvでunsetするという方法をとることにしました。

通常のGOPATHは~/に設定しています。通常のGO用のライブラリはここに入り、GAE用はsdkの中に入るという認識。

GAE用のプロジェクトの直下に下記を置く。

# .envrc
unset GOPATH
% env | grep GOPATH

もちろん空。

% goapp env | grep GOPATH
GOPATH="/usr/local/Cellar/app-engine-go-64/1.9.31/share/app-engine-go-64/gopath"

goapp経由でみるとsdkの場所が指定されています。

% goapp get goji.io    
# goji.io
/usr/local/Cellar/app-engine-go-64/1.9.31/share/app-engine-go-64/gopath/src/goji.io/mux.go:84: r.URL.EscapedPath undefined (type *url.URL has no field or method EscapedPath)

gojiをgetしようとするとエラーがでる。

/*
ServeHTTPC implements Handler.
*/
func (m *Mux) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
    if m.root {
        ctx = context.WithValue(ctx, internal.Path, r.URL.EscapedPath())
    }
    ctx = m.router.route(ctx, r)
    m.handler.ServeHTTPC(ctx, w, r)
}

ソースを読んでみたが、なぜr.URL.EscapePath()がundefinedなんだろう?m.rootとはなんだろう。GAEと関係あるんだろうか。

goのpluginを入れる。

https://gyazo.com/486bdc46a8c2ed8131a07847585c244d

SDKの設定をする。下記はhomebrewで入れたgo。

https://gyazo.com/8505e1ea93e0f7a0828a936853590927

ファイル保存時にgoimpoirtsする

File Watchers pluginを入れる。

https://gyazo.com/c448398e01cf5bb73faacc271978dc71

こんな感じで設定する。

https://gyazo.com/241041379d10e3df5bf1f27563804192

Immediate file synchronizationはonにするとおかしくなるのでoffにしておく。

https://gyazo.com/5c44daa1acd8847ba9002609ab29cbef

古いgojiのエントリーばっかりで新しいgojiのが見つからないので。

package main

import (
    "goji.io"
    "goji.io/pat"
    "net/http"
    "golang.org/x/net/context"
)

func main() {
    mux := goji.NewMux()
    mux.HandleFuncC(pat.Get("/"), func(ctx context.Context, w http.ResponseWriter, r *http.Request){
        // ...
    })
    mux.Handle(pat.Get("/*"), http.FileServer(http.Dir("public")))
    http.ListenAndServe("localhost:8000", mux)
}

public以下に置いたファイルにアクセスできる。