golangパッケージ、ginを使ったWEBサービスのテストができたので実際にどう構築するか考えてみました。
思いついたときにサービス追加しやすいことを前提に構成する。
基本構想
HTML表示をどこでやるか考える。
ginではAPIを書いてjavascriptで管理する方がサーバ負荷が小さく既存知識を生かせるように思うが、全体のコード量は増えそう。
HTMLテンプレート
html/template機能を使って表示までginで管理する。
gin.Context.HTML()
。Javascript + GO WEB API
ginでは静的ファイルの提供とAPI動作のみを書く。
表示側はjavascriptのフレームワークで管理する。
MVCフレームワークでgin APIを呼び出して仮想DOMで表示させるような運用。
主に使うのはgin.Context.JSON()
。
ファイル構成
ginソース内はサービス単位で分けるかMVCで分けると楽になると思う。
最終的に実行ファイル1つにしたいので(シングルバイナリ化)、テンプレートを含めた静的ファイル群は1つのフォルダにまとめておきたい。
サービスごとに分ける
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Project │ go.mod │ go.sum │ main.go │ handle.go │ ├─asset (View) │ ├─css │ ├─html (template) │ ├─img │ └─js │ └─service (Go files) ├─service1 │ main.go (Model) │ method.go (Contoroller) │ └─service2 main.go method.go |
mainパッケージのハンドラ内でimportがどんどん増えて混乱するかもしれない。
またjavascriptフレームワークメインで表示を行うのであればasset内はフレームワークの標準的なフォルダ構成になる。
MVCで分ける
モデルとコントローラーで分けるとサブパッケージは2つですむが、同名の構造体が使えなくなるので命名に気を付けないといけない。
1 2 3 4 5 6 7 8 |
service (Go files) ├─Model │ service1.go │ service2.go │ └─Contoroller service1.go service2.go |
ハンドラ関数の扱い
main.goはginエンジンの設定だけ書くようにしたい。
1 2 3 4 5 6 7 8 9 10 |
func main() { r := gin.Default() r.Static("/static", "./asset/static") r.LoadHTMLGlob("asset/html/*/*.html") r.GET("/", home) r.GET("/:f", features) r.Run() //=r.Run(":8080") } |
ハンドラ関数は大体小さい処理になるのでサービスが少ないうちはメインパッケージの別ファイルに書いて問題ないと思うが、数が増えた時を考えるとコントローラパッケージに入れてもいいかもしれない。
あるいはルーティングパッケージでも作ってそこにまとめる方法もある。