• home
  • Go言語を学習し始めて、簡単なCRUDアプリをクリーンアーキテクチャで作成するまで②

Go言語を学習し始めて、簡単なCRUDアプリをクリーンアーキテクチャで作成するまで②

こちらの記事は前回[Go言語を学習し始めて、簡単なCRUDアプリをクリーンアーキテクチャで作成するまで①|Wano Group Developers Blog](https://developers.wano.co.jp/1906/)の続きとなります。

とりあえず文法が一通り抑えられたので、チームの先輩@shunさんのアドバイスで、Goで簡単なCRUDアプリ(Web)作っていくことにしました。
とりあえず4段階くらいに分けるかあと思い、**4ステップに分けて順次進めていきました。**

このシリーズ目次

はじめに

こちらの記事は前回Go言語を学習し始めて、簡単なCRUDアプリをクリーンアーキテクチャで作成するまで①|Wano Group Developers Blogの続きとなります。

しかしこの記事から読まれても全く支障がないので、お好きに読まれてください!

とりあえず文法が一通り抑えられたので、チームの先輩@shunさんのアドバイスで、Goで簡単なCRUDアプリ(Web)作っていくことにしました。
とりあえず4段階くらいに分けるかあと思い、4ステップに分けて順次進めていきました。

②簡単なCRUDのWebアプリケーション作成

1.まずgoenvとdep導入

Gopkg.toml · dep
Golangをgoenvを使ってインストールしてみた – Qiita
goenvでgoをインストール 〜初心者向け〜 – Qiita
依存関係管理ツールdep(golang) – Qiita

goenvはgoのバージョン管理ツールで、depはパッケージ管理ツールです。どちらも私が配属されたVideo Kicksチームで採用しているということで使ってみました。
rubyでいうrbenvとBundlerということで、ここは問題なく導入。

2.echoでRESTAPI作る

【go】echoでapiサーバーを実装するときに最低限必要そうなことをまとめておく – とりあえずphpとか
Go の echo ってWebサーバーでサクッと REST しちゃう – Qiita

Echoというのは、Goでよく使われるフレームワークです。
うちのチームも採用しているようなので使ってみました。
API用途が多い、軽量のフレームワークになります。

だいたい公式ドキュメントEcho – High performance, minimalist Go web frameworkに使い方が書いてあるので、そこメインで参考にしました。わかりずらいところは上記サイト参照。
まずはJSON返す形で組んで動かして、echoの理解を深めました。

3.DB導入 Gorm使い方覚える

Mac へ MySQL を Homebrew でインストールする手順 – Qiita
GoでMySQLに接続する – Qiita
【GORM】Go言語でORM触ってみた – Qiita
GoのORマッパーでJoinデータのとり方を学ぶ! – イノベーション エンジニアブログ

Gormとは、Goでよく使われるORMです。
僕はフレームワークはRORしか使ったことがなかったので、別でORMを使っていくのは初めてでした。
でも結構使い安くて、公式ドキュメントGORM – The fantastic ORM library for Golang, aims to be developer friendly.もわかりやすいのである程度基本的なお作法はすぐ抑えやすいと思います。
前の記事で言及したpreload問題などなど、ORMあるあるかもなやばいSQL発行してるみたいなところは、業務で使いながら適切なクエリチューニングができるようにしていきます。

4.CRUDアプリ作成

Go言語のWebフレームワーク「Echo」を使ってみる ①(Hello World的な) – Qiita
Go言語のWebフレームワーク「Echo」を使ってみる ②(リクエストパラメータの扱い) – Qiita
Go言語 – HTMLテンプレートの使い方 – 覚えたら書く
golang : template の range で index を使う – i++

1~3まで行えていれば、あとはwebのview側どうするか、ってとこだけだと思います。そこでechoのTemplates | Echo – High performance, minimalist Go web frameworkを利用して、renderingしていくのがメジャーのようです。
RORとかのフルスタックフレームワークにおんぶに抱っこだったのでわりかし使いづらさを感じましたが、こちらも公式リファレンスが一番わかりやすい気がします。その他細かいとこ(template内でのスライスの回し方とか)は上記のサイト参考にしながら進めました。

そうしてざっくり作ったのがこちらになります。
GitHub – takafk9/echo_crud

細かいエラーハンドリングとかログ管理とか一切してないです。とりあえずお試しで一通りいじってみた感じです。
突っ込みどころばかりだと思うのですが、0からとりあえず簡単な仕様を作ってみたい方向けということで。(許して)

Goはhtmlレスポンス拡張put,delete対応してないので、下記のサイトを参考に実装しようと思ったのですが、うまくいかず保留中。
[go,echo]formからputをリクエスト~methodOverRide~ – Qiita

@y_ussieさんの実装Go言語のWebフレームワーク「Echo」を使ってみる ②(リクエストパラメータの扱い) – Qiitaをかなり参考にしました。(大感謝)

複数画面ある場合どうtemplate扱おうかしら、って思ってたんですが、@y_ussoeさんのmapにtemplate入れるの案良いな、と思って採用していました。

main.go@y_ussie

// Render はHTMLテンプレートにデータを埋め込んだ結果をWriterに書き込みます。
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
    return templates[name].ExecuteTemplate(w, "layout.html", data)
}

// 初期化を行います。
func init() {
    loadTemplates()
}

// 各HTMLテンプレートに共通レイアウトを適用した結果を保存します(初期化時に実行)。
func loadTemplates() {
    var baseTemplate = "templates/layout.html"
    templates = make(map[string]*template.Template)
    templates["hello"] = template.Must(
        template.ParseFiles(baseTemplate, "templates/hello.html"))
    templates["hello_form"] = template.Must(
        template.ParseFiles(baseTemplate, "templates/hello_form.html"))
}

ただ、initの処理で画面数だけtemplate初期化して用意しておく必要はないかなと、以下のようにgetTemplateメソッド作って、nameに対応したtemplateをBaseTemplateに都度マージして、返すようにしました。

main.go@fukubaka0825

// Render はHTMLテンプレートにデータを埋め込んだ結果をWriterに書き込みます。
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
    return getTemplate(name).ExecuteTemplate(w, "layout.html", data)
}

func getTemplate(name string)(*template.Template){
    switch name {
    case "posts_all":
        return template.Must(template.ParseFiles(_const.BaseTemplate, _const.PostsAll))
    case "update_post_form":
        return template.Must(template.ParseFiles(_const.BaseTemplate, _const.UpdatePost))
    default:
        return nil
    }
}


※2019/2/26 訂正
指摘があったため訂正です。

// template情報をキャッシュ
var templates = template.Must(template.ParseFiles("edit.html", "view.html"))    

templateキャッシュ【Go】 – 技術向上

上記の例のように、template.Mustでパース結果をキャッシュして、その結果をMapに詰めて
取り出しやすくするのは非常に理にかなっているので、@y_ussieさんの実装のままの方が良いみたいです。
圧倒的改悪を施していた、、、ここで勉強できてよかった!


ディレクトリ分けとしてはオーソドックスなMVCな感じで分けました。

ただ今の時流でGoでコテコテのMVCって流石に、、、ってなってうちのPM(VPoE)に相談したところ、
「クリーンアーキテクチャで作り変えて見れば?軽くテストまで書いてみると恩恵も理解できて良いと思うよ」
とアドバイスをいただいたので、作り変えてみることに。
いやでもしかし、内心 「クリーンアーキテクチャって聞いたことあるけどなんぞ???」 って感じで、、、、、、、
ここから③に続きます。明日か明後日にあげれると思います。

ではまた次回!!!!

The Go gopher was designed by Renée French.