DRYな備忘録

Don't Repeat Yourself.

【Go言語】`net/http`パッケージことはじめ

さっきマックで女子高生が「えーまだ生net/http使ったことないのーw マジウケるんですけどー」って話してた。やばい。

最小限

とりあえず、HandleFuncHandleを用いた最小限のサーバ

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/

f:id:otiai10:20141006192948j:plain

いけてる

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)
 }

f:id:otiai10:20141006194213j:plain

いけた、が、そろそろダルくなってくる

発明済みの車輪

もともとオールインワン感あるのはrevel。ルーティングだけにしぼってる感あるのはhttprouter。gorilla、martiniは必要に応じてミドルウェアを追加していくスタイルっぽい。

雑感

ちゃんと生でnet/http触らなきゃなと思ってたので、そのきっかけになったのでよかった。引き続きたくさん勉強しないと死ぬっぽい状況にある。

DRY