goの標準
goでhttpの処理を書きたいときはnet/httpパッケージを使う。
強力なパッケージなので、基本これを使うで、やりたいことの殆どはまかなえてしまうと思う
http.Get(url)
package main import ( "fmt" "io/ioutil" "net/http" ) func main() { resp, err := http.Get("http://www.google.co.jp") if err != nil { fmt.Printf("err: %v", err) } defer resp.Body.Close() b, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Printf("ioutil err: %v", err) } fmt.Printf("html: %v", string(b)) }
http.NewRequest(url)
単純にGetをするだけであれば http.Get(url)
で事足りると思われるが、その他のMethodにも対応させるために、httpクライアントを明示的に作ることも可能
package main import ( "fmt" "io/ioutil" "net/http" ) func main() { req, err := http.NewRequest("GET", "http://www.google.co.jp", nil) if err != nil { fmt.Printf("new request err: %v", err) } client := http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("request response err: %v", err) } defer resp.Body.Close() b, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Printf("ioutil err: %v", err) } fmt.Printf("html: %v", string(b)) }
GAEの標準
GAE/Goでhttpを書きたいときにはちょっと1つ考慮しておかなければいけないことがある。
- GAE/Goでは、GAEのContextを使わないといけない
- 通常のリクエストからGAEのContextを作成し、それを使ってhttpのrequest/responseを実装する
package main import ( "net/http" "io/ioutil" "google.golang.org/appengine" "google.golang.org/appengine/log" "google.golang.org/appengine/urlfetch" ) func init() { http.HandleFunc("/", SampleHandler) } func SampleHandler(w http.ResponseWriter, r *http.Request) { ctx := appengine.NewContext(r) // GAEのContextを作成する httpClient := urlfetch.Client(ctx) resp, err := httpClient.Get("http://www.google.co.jp") if err != nil { log.Debugf(ctx, "html: %v", err) } defer resp.Body.Close() b, err := ioutil.ReadAll(resp.Body) if err != nil { log.Debugf(ctx, "html: %v", err) } log.Debugf(ctx, "html: %v", string(b)) }
ハマったところ
- gaeのプロジェクトの最小構成単位はhandlerを受け付けるgoのファイルとapp.yamlがあること。
- しかし、この2つのファイルは同じ階層においては行けない
- my-project - app.yaml - src - main.go
というディレクトリ構成にする必要がある。
- gaeではmain関数でなく
init()
を使う。 main()
を使っていた最中にずっと起動後localhost:8080
に繋いでも404 page not found
が返ってきてしまっていた。- gaeのhttpのHandlerには
http.ListenAndServe()
メソッドは使わない。