お首が長いのよお首が長いのよ

チラシの裏よりお届けするソフトウェアエンジニアとして成長したい人のためのブログ

2022-03-12

Go言語学習(net/http における HTTP サーバー構築)

net/http パッケージは http クライアント、サーバーとしての役割に必要な処理を集めたパッケージ。

今回はサーバーとしての使い方を学んだ。

最小構成

最小構成といいつつ待受アドレスは変更している。第一引数は何も設定しなければ :80 で待受する。 このコードの場合、「ハンドラ」が渡されていないので 404 not found になる。

go
1package main
2
3import "net/http"
4
5func main () {
6	// 第一引数は待受するアドレス。
7	// 第荷引数はハンドラ
8	http.ListenAndServe("127.0.0.1:8080", nil)
9}
10
11

http.Server 構造体

http.Server 構造体からインスタンスを生成する際にサーバーの設定値をいじる。 上記例をそのまま http.Server 構造体インスタンスで書き換えるとこうなる。

go
1server := http.Server {
2	Addr: "127.0.0.1:8080"
3	Handler: nil
4}
5

ハンドラ

  • ハンドラ: ServeHTTP メソッドを持つインターフェースを指す
  • ハンドラ関数: ハンドラのように振る舞う関数。後述するが、ハンドラを毎回インスタンス化するのは大変なので、ハンドラのように扱える関数を定義することで簡略化できる。

HelloHandler というエイリアスを持つ空構造体に対して ServeHTTP メソッドを実装し、 handler := MyHandler{} でインスタンス化してそいつを http.ServerHandler に割り当てる

go
1
2type HelloHandler struct {}
3
4func (h *HelloHandler ) ServeHTTP(w http.ResponseWriter, r *http.Request) {
5	fmt.Fprintf(w, "Hello World!")
6}
7
8func main () {
9	handler := HelloHandler{}
10	server := http.Server {
11		Addr: "127.0.0.1:8080",
12		Handler: &handler,
13
14	}
15	server.ListenAndServe()
16}
17
18

複数のパスをハンドラで処理する

go
1type HelloHandler struct {}
2
3func (h *HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
4	fmt.Fprintf(w, "Hello!")
5}
6
7type WorldHandler struct {}
8
9func (h *WorldHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
10	fmt.Fprintf(w, "World!")
11}
12
13func main () {
14	fmt.Println("HTTP srerver is running")
15	hello := HelloHandler{}
16	world := WorldHandler{}
17
18	server := http.Server {
19		Addr: "127.0.0.1:8080",
20
21	}
22	http.Handle("/hello", &hello)
23	http.Handle("/world", &world)
24
25	server.ListenAndServe()
26}
27
28

ハンドラ関数

ハンドラ関数は、 ServeHTTP と同じ引数 (http.ResponseWriter, r *http.Request) を取る関数。 ハンドラは ServeHTTPメソッドを持つインスタンスなので、ハンドラでリクエストを処理するときは必ず実体化しなければいけない。

ハンドラ関数であれば、 http.HandleFunc の引数に処理するパスと、作成した関数を渡すことで同じことができる。

複数のパスをハンドラ関数で処理する

go
1
2func hello(w http.ResponseWriter, r *http.Request) {
3	fmt.Fprintf(w, "Hello! HandlerFunc~")
4}
5
6func world(w http.ResponseWriter, r *http.Request) {
7	fmt.Fprintf(w, "World! HandlerFunc~")
8}
9
10func main () {
11	fmt.Println("HTTP srerver is running")
12
13	server := http.Server {
14		Addr: "127.0.0.1:8080",
15
16	}
17
18	// HandleFunc 関数は HandlerFunc 型を第2引数に取る。
19	// HandlerFunc 型の関数は http.ResponseWriter, *http.Request を引数に持つ関数である。
20	http.HandleFunc("/hello", hello)
21	http.HandleFunc("/world", world)
22
23	server.ListenAndServe()
24}
25
26

参考

よかったらシェアしてください!