さっきマックで女子高生が「えーまだ生net/http使ったことないのーw マジウケるんですけどー」って話してた。やばい。
最小限
とりあえず、HandleFunc
やHandle
を用いた最小限のサーバ
package main import ( "fmt" "net/http" // "io/ioutil" ) // ResponseWriter, *Request を引数に持つ関数 // http.HandleFuncの引数になれる func MyHandleFunc(rw http.ResponseWriter, req *http.Request) { n, e := rw.Write([]byte("`MyHandleFunc` just handled /foo")) fmt.Println(n, e) } // 一方、http.Handlerインターフェースを満たすサムシング // http.Handleの引数になれる type MyHandler struct{} func (my *MyHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { n, e := rw.Write([]byte("`MyHandler` just handled /bar")) fmt.Println(n, e) } func main() { // 1) HandleFuncで関数を与える(クロージャでももちろん可能) http.HandleFunc("/foo", MyHandleFunc) // 2) HandleでHandlerインターフェースなサムシングを与える handler := &MyHandler{} http.Handle("/bar", handler) // 第二引数がnilだと、http.HandleFuncやhttp.Handleで追加された // http.DefaultServeMuxを採用する // `usually nil`って言ってる -> http://golang.org/pkg/net/http/ http.ListenAndServe(":9090", nil) }
Header指定
Headerの指定が欲しくなるところ. http.ResponseWriter
型にはHeader()
というメソッドがある.
http - The Go Programming Language
diff --git a/server.go b/server.go index b7e4b23..eea444e 100644 --- a/server.go +++ b/server.go @@ -22,6 +22,14 @@ func (my *MyHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { fmt.Println(n, e) } +type JsonHandler struct{} + +func (h *JsonHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + rw.Header().Add("Content-Type", "application/json") + n, e := rw.Write([]byte("{\"res\":\"OK\"}")) + fmt.Println(n, e) +} + func main() { // 1) HandleFuncで関数を与える(クロージャでももちろん可能) http.HandleFunc("/foo", MyHandleFunc) @@ -30,6 +38,10 @@ func main() { handler := &MyHandler{} http.Handle("/bar", handler) + // 3) application/jsonを返すハンドラ + jsonHandler := &JsonHandler{} + http.Handle("/json", jsonHandler) + // 第二引数がnilだと、http.HandleFuncやhttp.Handleで追加された // http.DefaultServeMuxを採用する // `usually nil`って言ってる -> http://golang.org/pkg/net/http/
いけてる
Method振り分け
同URIのリクエストで、MethodがGETじゃなくてPOSTは?
diff --git a/server.go b/server.go index eea444e..76b8772 100644 --- a/server.go +++ b/server.go @@ -26,7 +26,14 @@ type JsonHandler struct{} func (h *JsonHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { rw.Header().Add("Content-Type", "application/json") - n, e := rw.Write([]byte("{\"res\":\"OK\"}")) + var n int + var e error + switch req.Method { + case "POST": + n, e = rw.Write([]byte("{\"res\":\"I got `POST`\"}")) + case "GET": + n, e = rw.Write([]byte("{\"res\":\"I got `GET`\",\"data\":{\"name\",\"otiai10\"}}")) + } fmt.Println(n, e) }
いけた、が、そろそろダルくなってくる
発明済みの車輪
- mux - Gorilla, the golang web toolkit
- Routing
- go-martini/martini · GitHub
- Why I wrote gocraft/web - UserVoice Developer
- julienschmidt/httprouter · GitHub
もともとオールインワン感あるのはrevel。ルーティングだけにしぼってる感あるのはhttprouter。gorilla、martiniは必要に応じてミドルウェアを追加していくスタイルっぽい。
雑感
ちゃんと生でnet/http触らなきゃなと思ってたので、そのきっかけになったのでよかった。引き続きたくさん勉強しないと死ぬっぽい状況にある。
DRY