#技術書の内容の理解を深めたい
今読んでいる技術書の内容で大事だと思った部分を少しずつまとめていきたいと思います。
今回読んでいる本はこちら
Goプログラミング実践入門
購入した理由は、レビューの内容も良かったのですが、フレームワークを利用しないでWebサービスを構築することによって、webサービス構築に必要な知識を身につけましょうというもの。
普段はフレームワークによって隠蔽されているhttp関連の処理の理解を深めるといったところですかね。このコンセプトが気に入りました。
フレームワークってあんまり好きじゃないんですよね(爆)
#マルチプレクサとは
この本を読み進めていくうちに理解できなかった言葉が「マルチプレクサ」。読み進めていっても詳細な説明は一切なし。なのでググってみた。
以下wikipedia参照
マルチプレクサ、多重器、多重装置、多重化装置、合波器(multiplexer)は、ふたつ以上の入力をひとつの信号として出力する機構である。通信分野では多重通信の入口の装置、電気・電子回路では複数の電気信号をひとつの信号にする回路である。しばしばMUX等と略される。
だそうです。
通信でも電気/電子回路でも使われている言葉ということで、一応一般的な言葉なので説明が省かれていたということなんでしょうねぇ。
#ハンドラって?
今回はgo言語でwebサーバーを作成する際にこのマルチプレクサが登場します。
このwebサーバー構築におけるマルチプレクサを理解するためにはハンドラを理解しなければいけないようでハンドラの実装についての説明が始まります。
Go言語においてハンドラ(Handler)とは、ServeHTTPというメソッドを持ったインターフェースのことです。このメソッドは、インターフェースHTTPResponseWriterと構造体Requestへのポインタという2つの引数をとります。略
ServeHTTP(http.ResponseWriter, *http.Request)
お恥ずかしい限りですが、僕はハンドラという言葉の意味をいまいち要領がつかめておりませんでした。
javascriptをやっていてもたまに出てくる言葉ですが、イベントとハンドラの違いがいまいちわかっていませんでした。イベントハンドラともいうし・・・
Go言語におけるハンドラとはServeHTTPというメソッドを持っているインターフェースはハンドラと言って良いらしいです。
これだけではよくわからないので、実装で説明されます。
package main
import (
"fmt"
"net/http"
)
type MyHandler struct{}
func ( h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
fmt.Fprintf(w, "Hello Qiita!")
}
func main() {
handler := MyHandler{}
server := http.Server{
Addr: "127.0.0.1:8080",
Handler: &handler,
}
server.ListenAndServe()
}
実装で説明してくれるというのはまさにエンジニア向けという感じでとても好印象ですね。
このコードによって起動されたwebサーバーにアクセス(ブラウザでhttp://localhost:8080を入力)すると「Hello Qiita!」が出力されます。
ServeHttpメソッドのシグネチャのうち( h *MyHandler)の部分はGo言語でレシーバと呼ばれる役割のある記述になります。
main関数の中で定義しているserver構造体に自前の空のハンドラを定義する。そのハンドラと自前のServeHTTPをレシーバで紐付ける。
サーバーが起動すると、Addrへのアクセス時にハンドラに紐付いたServeHTTPが呼び出される。という流れ(なぜアクセス時にハンドラに紐付いたServeHTTPが呼び出されるのかというロジックまでは追えず・・・わかる人いたら教えて欲しいっす)
今回の例では8080番ポートへのアクセスをHello Qiitaとするロジックしかありませんが、マルチプレクサというハンドラを利用することによって(マルチプレクサもハンドラの一つという扱いになっている)、複数のリクエストに対し、そのリクエストのURL(パス)に応じたレスポンスをふり分けることが可能になるということみたいです。
#マルチプレクサの実装例
以下が例です。
package main
import (
"fmt"
"net/http"
)
type HelloHandler struct{}
func ( h *HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
fmt.Fprintf(w, "Hello!")
}
type QiitaHandler struct{}
func ( h *QiitaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
fmt.Fprintf(w, "Qiita!")
}
func main() {
hello := HelloHandler{}
qiita := QiitaHandler{}
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.Handle("/hello", &hello)
http.Handle("/qiita", &qiita)
server.ListenAndServe()
}
これでhttp://localhost:8080/hello と http://localhost:8080/qiita で出力内容を変更できるはずです。
今度はserver構造体のHandlerを未設定としています。これによりデフォルト値としてhttp.DefaultServeMuxが設定されます。つまりマルチプレクサを使うということを宣言することになります。
http.Handle(pattern string, handler Handler)は内部的にDefaultServeMux.Handle(pattern, handler)を実行しているのでマルチプレクサにパターンとハンドラを登録している。
#結論
自分の理解としては、ハンドラはリクエストに対して具体的な処理が定義されているもの全般。
マルチプレクサはハンドラのうちの一つで、いろんなリクエストに対して、ハンドラの振り分けをしてくれるjavaでいうサーブレットのweb.xmlみたいなもん。
とまぁ、自分の理解はこんなもんです。
細かい処理の説明が不十分とか理解が合っていないなどの指摘お待ちしてます。