Goでルーティング(gorilla/mux)
概要
GAEのgoランタイムでDatastoreに繋いでCRUDしてみたい。
その前にgo言語自体全然書いてないのでルーティングをザクっと実装してみる。
その後でDatastoreへの接続を書いていく。ちょっとずつ進めてこう。
構築
リクエストのルーティング処理
ハンドラーの登録
とりあえず、GET,POST,PUT,DELETEあたりをやりたい
前回のHello, Worldではnet/httpでリクエストをさばいてたけど、gorilla/muxなるものが人気らしい。 それで書いてみる。
ListenAndServeメソッドの第2引数にルーティング情報を記載したハンドラーを渡してみる。
func main() { port := os.Getenv("PORT") if port == "" { port = "8080" log.Printf("Defaulting to port %s", port) } log.Printf("Listening on port %s", port) log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), registerHandlers())) }
ルーティングの定義
メソッド、パスに準じた処理を記載。
func registerHandlers() *mux.Router { router := mux.NewRouter() router.Methods("GET").Path("/members").Handler(appHandler(listHandler)) router.Methods("POST").Path("/members").Handler(appHandler(createHandler)) router.Methods("PUT").Path("/members/{id:[0-9]+}").Handler(appHandler(updateHandler)) router.Methods("DELETE").Path("/members/{id:[0-9]+}").Handler(appHandler(deleteHandler)) return router }
エラー返却時の記述を簡略化
Error handling and Go - The Go Blogに書かれているように自身の定義したエラー(appError)を返却するappHandlerをかましてハンドラー登録すると、http.ResponseWriter
に毎度エラーを書き込まなくても、エラーを返却するだけでよろしくエラー返却してくれて冗長性を無くしてくれるらしい!
type appError struct { Code int Message string Error error } type appHandler func(w http.ResponseWriter, r *http.Request) *appError
ただし、ただエラー返却するだけではnet/http
が理解してくれないので
ServeHTTP
メソッドを作成して理解させる必要があるらしい。
func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if e := fn(w, r); e != nil { log.Printf("Handler error: status code: %d, message: %s, underlying err: %#v", e.Code, e.Message, e.Error) http.Error(w, e.Message, e.Code) } }
ルーティング毎の処理(一覧表示)
あとはルーティングにマッチした際の処理を記載する。
本当はDatastoreからデータ取りたいが、とりあえず適当に会員一覧を返却させとく。
type Member struct { Name string } type Members []Member func listHandler(w http.ResponseWriter, r *http.Request) *appError { response, jsonError := json.Marshal(Members{ Member{ Name: "Name1", }, Member{ Name: "Name2", }, }) if jsonError != nil { return appErrorFormat(jsonError, "%s", jsonError) } w.Header().Set("Content-Type", "application/json") _, writeError := w.Write(response) if writeError != nil { return appErrorFormat(writeError, "%s", writeError) } return nil }
実行
あとはコマンド叩いてローカル環境で色々アクセスしてみる。
# go run main.go go build ./ucwork-go
GETでhttp://localhost:8080/members
にアクセスしたらこんなん返ってきた!!
[ { "Name": "Name1" }, { "Name": "Name2" } ]
まとめ
GCPのサービスザクっと触ってみるのが目的なのにまた脱線してしまった。。。
まぁせっかくならGoogleにロックインされにかかるためにgoも学習しとこー