Go言語(Golang)でMVCモデルを実現する 前編

はじめに

この記事では、Go言語(以下、Golangと表記)でのWEBアプリケーション構築の習得を目的に、MVCモデルで開発を進めることを考え、VC部分の実装を行いました。
次の記事ではMの部分である、DBを絡めたI/Oを含めて完全なMVCモデルでの実装を目指していく予定です。

用意した環境

  • OS: Windows10
  • Golang: 1.15.2
  • フレームワーク:Gin

環境変数のGOPATHは以下で設定してあります。
GOPATH = C:\Users\murai\Documents\GolangProject

環境構築が必要であれば前回の記事を参考にしてください。
https://bsblog.casareal.co.jp/archives/4582

この記事での目標

まずは簡易的な会員管理システムを作っていこうと思うので、
最低限必要になりそうな以下4画面を表示することを目標としていきます。

  • トップ画面
  • 会員一覧画面
  • 会員追加画面
  • 会員編集画面

会員編集画面のみ会員ごとに表示する内容が変わるので、
URLからIDを取得して表示を切り替えられるような作りにします。

ディレクトリ構成

この記事で使用するプロジェクトのディレクトリ構成は以下になります。

GolangProject
  - src
    - github.com
      - gin-gonic
        - gin                   // ginフレームワーク
      - murai
        - go-user-management    // プロジェクトフォルダ
          - controller
            - top
              - index.go
            - user
              - add.go
              - edit.go
              - list.go
          - server
            - router.go
          - view
            - index.html
            - user-add.html
            - user-edit.html
            - user-list.html
          main.go

Controllerを作成する

MVCのCの部分にあたるControllerを作成します。
機能ごとに1ファイルとしていきたいので以下のようにファイルを作成しました。

index.go

package top

import (
    "github.com/gin-gonic/gin"
)

func IndexDisplayAction(c *gin.Context){
    c.HTML(200, "index.html", gin.H{})
}

add.go

package user

import (
    "github.com/gin-gonic/gin"
)

func UserAddDisplayAction(c *gin.Context){
    c.HTML(200, "user-add.html", gin.H{})
}

edit.go

package user

import (
    "github.com/gin-gonic/gin"
)

func UserEditDisplayAction(c *gin.Context){
    id := c.Param("id")    // URLからIDを取得して表示を分ける
    c.HTML(200, "user-edit.html", gin.H{
      "id": id,            // htmlファイルに値を渡す
    })
}

list.go

package user

import (
    "github.com/gin-gonic/gin"
)

func UserListDisplayAction(c *gin.Context){
    c.HTML(200, "user-list.html", gin.H{})
}

会員編集画面のコントローラであるuser-edit.goでは、
URLからIDを取得して会員を判定する作りにしています。

Viewを作成する

MVCのVの部分にあたるViewを作成します。
今回は表示できることが目的なので、内容はかなり簡素にしました。

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>会員管理トップ</title>
</head>
<body>
    <h1>会員管理トップ</h1>
    <a href="/user"><h3>会員一覧</h3></a>
    <a href="/user/add"><h3>会員追加</h3></a>
</body>
</html>

user-add.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>会員追加</title>
</head>
<body>
    <h1>会員追加</h1>
</body>
</html>

user-edit.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>会員編集</title>
</head>
<body>
    <h1>会員編集</h1>
    <p>会員ID:{{.id}}の編集ページです。</p>
</body>
</html>

user-list.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>会員一覧</title>
</head>
<body>
    <h1>会員一覧</h1>
    <a href="/user/edit/1"><h3>会員1を編集</h3></a>
</body>
</html>

会員編集画面ではidが問題なく渡せていることを確認するため、
user-edit.htmlの{{.id}}で代入を行っています。

本当であれば、routerで「router.LoadHTMLGlob(“view/*/**.html”)」のようにして、
view配下にuserフォルダを作成して会員関係のファイルは格納したかったのですが、
上手く読み取れなかったため、ファイルの命名を「user-機能」のようにして分かりやすくしています。

ルーティング設定

Golangの仕様上、main.goに処理を全て書くこともできますが、
流石にごちゃごちゃしてしまいそうなので、
main.goではルーティングや、今後追加するであろう他の設定など、
管理しやすく切り出したファイルをインポートしていく形にしています。
今回はルーティング設定であるrouter.goを切り出して実装を行いました。

router.go

package server

import (
    "github.com/gin-gonic/gin"
    "github.com/murai/go-user-management/controller"
)

func GetRouter() *gin.Engine {    // *gin.Engineの表記は返り値の型
    router := gin.Default()
    router.LoadHTMLGlob("view/*.html")

    router.GET("/", controller.IndexDisplayAction)
    router.GET("/user", controller.UserListDisplayAction)
    router.GET("/user/add", controller.UserAddDisplayAction)
    router.GET("/user/edit/:id", controller.UserEditDisplayAction)

    return router
}

main.go

package main

import (
    "github.com/murai/go-user-management/server"
)

func main() {
    r := server.GetRouter()
    r.Run(":8080")
}

動作確認

http://localhost:8080/

http://localhost:8080/user

http://localhost:8080/user/add

http://localhost:8080/user/edit/1

この記事の目標通り、
4画面の表示に成功しました。

まとめ

Golangはどうも自由度が高すぎるようで、Webフレームワークを利用していても、フォルダの構成はあまり決まった形がないみたいでした。
そのため、どのようにすれば今後実装がスムーズに行えるかなど、
先を見越してフォルダ構成やファイル構成を決めないと、
管理が難しくなりそうだなと感じました。
その反面、自分が管理しやすい構成にすることで開発効率は上がりそうだとも感じました。
今後もいろいろと試行錯誤していきたいと思います。


--------------------------
システム開発のご要望・ご相談はこちらから

コメントを残す

メールアドレスが公開されることはありません。