genzai0の日記

にっき

Build web application with Golangの備忘録

概要

Goはどのようにしてweb作業を行うか · Build web application with Golang

astaxieさんのgitbookでわからなかったところをメモする

3章を見ていきます

理解が甘いところがあるので、間違ってたら突っ込んでください。

3.2章 簡単なwebサーバー

main関数内からです。

そもそものhttprequestの実装、http.HandleFunc()、http.ListenAndServe()メソッドをそれぞれ解説します。

httprequest

golang.org

コメントアウトを消したものを以下に引用します。

type Request struct {
    Method string
    URL *url.URL
    Proto      string // "HTTP/1.0"
    ProtoMajor int    // 1
    ProtoMinor int    // 0
    Header Header
    Body io.ReadCloser
    GetBody func() (io.ReadCloser, error) // Go 1.8
    ContentLength int64
    TransferEncoding []string
    Close bool
    Host string
    Form url.Values
    PostForm url.Values // Go 1.1
    MultipartForm *multipart.Form
    Trailer Header
    RemoteAddr string
    RequestURI string
    TLS *tls.ConnectionState
    Cancel <-chan struct{} // Go 1.5
    Response *Response // Go 1.7
}

Cか何かを触っていた時にhttpリクエストは構造体だ、という言葉をどこかで聞いた覚えがありますが、goのhttpリクエストは構造体みたいですね。

最近学んだことですが、そもhttpリクエストとはクライアント-サーバ間のやりとりのメッセージの一つです。リクエストとレスポンスがありますが、要り様なのはリクエストなので割愛します。深くはsocket通信など調べてみると具体的な形が分かると思います。

簡単な例としてchromeでctrl+shift+iなどでデベロッパーツール、Networkタブに切り替えて(読み込みのためreloadして)Nameから適当なファイルをクリックしたHeadersを見て、こんな感じかーとだけ思っておけば大丈夫です。status codeとか、そういうのが書いてあると思います。

httpリクエストは大まかに3つに分けられ、それぞれリクエストライン、ヘッダー、メッセージボディと呼びます。上からこの順番で並んでいます。

リクエストラインが構造体のMethod+Url+Protoで成り立ちます。(Protoはプロトタイプではなくて、プロトコルの"プロト"ですね。きっと)

GET (任意のURL) HTTP/1.1 がよくある例です

順当に見ればヘッダーなのですが一度割愛して、メッセージボディが"送りたい情報本体"になります。よくあるhtmlを送るならおそらくから始まるタグから中の文書全体までがメッセージボディです。細かく追記すると、分けて送るので、メッセージボディ一つに文書全体が入っているとは限りません。

最後にヘッダーが残り全てです。情報が様々入ってます。

http.HandleFunc

qiita.com

m0t0k1ch1st0ry.com

本題に移ります。main文の一行目http.HandleFuncでは与えられたハンドラをパターンに登録するらしいです。

https://github.com/golang/go/blob/7662e6588c9433f1219e0a0c46bc563ba3f93f98/src/net/http/server.go#L2369

ここから先はServeMuxを読まなきゃならないみたいなので撤退。とりあえず、自分で定義したハンドラはこの関数を通過させることによって安全に利用できるのかな(?)

第二引数のハンドラから次に、sayhelloNameに移ります。

sayhelloName

この関数ではハンドラーとして、返したい(表示したい)具体的な処理と内容を記述します。メッセージボディに投げるものをここでやっておくイメージですね。(ハンドラーっていう語は範囲が広くて難しい)

この関数でrequestにhttpリクエストが入っているはずです。ResponseWriterはtimeoutWriterで定義されており、エラーで使うので今は気にしないでおきましょう。

ParseFormではフォーム情報が取得されます。山ほどあるヘッダー情報の中から、フォームだけを取り出します。/?以降に入力した配列の形で一行目に表示されるものです。

developer.mozilla.org

urlの最後の/に続き?から配列名=値の組を&で繋いでURLに入力するとこの形式でフォームを送ったことになるみたいですね。

余談ですがおそらく、URL.Schemeはnet/urlの構造体変数でparseする関数を変えれば動くと思います。

後はfor-rangeでkey-value形式で表示をしているだけです。

試しに、例のurlの後に&okasi=tabetaiと入力するとkey:okasiにvalue:tabetaiが追加されると思います。

http.ListenAndServe

main文二行目のものですね。err変数に代入しているみたいですが、その名の通りlistenをよろしく処理してくれるみたいですね。コメントを読んでみると、srv.AddrにTCPのネットワークアドレスが入っているのでそれを利用するらしい。Serve関数まで読んで断念した。全体を読まないとだめね。

やっていること自体は、よしなにサーバを待ち状態に設定するというところで。

qiita.com

とても参考になった記事だった。

まとめ

bind、listen、accept、sendがListenAndServeに集約されている。

ルーティング設定とハンドラーの設定ををHandleFuncで行っている。

ハンドラーは実処理部(?)。やりたいことを記述する。

感想

曖昧なので完全理解したい。