前提
- Golangで超シンプルにローカルでwebアプリ起動するところまで の続き
- 筆者はほとんどJavaしかやってきていない
目的
-
handler()
を別クラスにわけたい。mainがあるクラスに機能が集約するのが生理的に気持ち悪いため。
やったこと
ディレクトリ構成
golang_webapp_sample
└── src
└── main
├── golang_webapp_sample.go
└── handler
└── http_handler.go
ソース
とりあえずhandler()
を別クラスにする。
この時Handler()
と先頭大文字にすることで外部参照可能なメソッドとなる。
package handler
import (
"fmt"
"net/http"
)
func Handler(writer http.ResponseWriter, request *http.Request){
fmt.Fprintf(writer, "Hello World!")
}
次にメインクラス。
importは以下のように"golang_webapp_sample/src/main/handler"
とすれば別クラスのメソッドが呼べる。
package main
import (
"golang_webapp_sample/src/main/handler"
"net/http"
)
func main() {
http.HandleFunc("/", handler.Handler)
http.ListenAndServe(":8080", nil)
}
参考:Go言語のpackageの作り方: 長くなったコードを別ファイルに切り出す方法
確認
-
go run golang_webapp_sample.go
で起動 - http://localhost:8080/ にアクセス
- 画面に
Hello, World!
と表示されたら勝ち
勝った。
この段階で発生した疑問点
クラス…?
なんとなくファイル名を分けてこそみたが、よくよく考えてみると、ここまでクラス定義なんかしていないことに今更気づく。
参考: golang メソッドについてまとめてみた。
ではクラスの説明〜と言いたいところなんですが、golangにはクラスという概念がありません。ではクラスの説明〜と言いたいところなんですが、golangにはクラスという概念がありません。なので、メソッドは型に対して紐づくものまででそれ以上はありません。
なるほど、Golangにはクラスという概念はない。
メソッドの先頭文字が大文字かどうかで参照可能範囲が決まるだけである。
目的にmainがあるクラスに機能が集約するのが生理的に気持ち悪い。
と記載したが、この発想が前提から間違っていたのだ。
(とはいえ、振る舞いを役割によって分割するのは設計上好ましいことに間違いはないだろう。結合は疎に、凝集度は高く)
メソッドの引数…??(未解決 → 解決)
…?これ何で動いてんの?
〜〜
http.HandleFunc("/", handler.Handler)
〜〜
〜〜
func Handler(writer http.ResponseWriter, request *http.Request){
〜〜
- **
handler.Handler
がもうわからない。**百歩譲ってhandler.Handler()
ならわかる。そんなメソッドは定義していないが。 - 引数いらんの???何で????
- メソッドと思って書いた
Handler()
は、メソッドのようでメソッドじゃない、少しメソッドな関数なのではという仮説。ここはGolangワールド、Javaのお作法とは違うのだ。
8/26 追記
@K-juju さんからのコメントにて腹落ち。ありがとうございました!
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
http.HandleFuncの定義は上記になります。
引数を見ていただくとわかると思うのですが、第二引数の型が func(ResponseWriter, *Request) となっています。
今回の場合で考えてみると、
handler.Handler の型は func(ResponseWriter, *Request) です
handler.Handler() は(引数は省略します)そもそも返り値がないので、型とかありません。
おそらく勘違いされている点は、
http.HandleFunc("/", handler.Handler)
の handler.Handler の部分は、関数を引数としているだけで、関数を呼び出しているわけではないです。
したがって引数はいらないということだと思います。
関数を引数としているだけで、関数を呼び出しているわけではない
Java的にメソッドじゃメソッドじゃと思ってたんですが、そもそもこの時点で関数を呼び出してるわけじゃなかった。
ありがとうございます!
次やること
-
上記、メソッドについての疑問を解決する→ 解決 - Dockerのimageにして起動する → https://qiita.com/nitt_san/items/6cba1e422dcdd6098f06
- Kubernetesに放り込んで色々試す