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

## このシリーズ目次
- [Go言語を学習し始めて、簡単なCRUDアプリをクリーンアーキテクチャで作成するまで① - Qiita](https://qiita.com/fukubaka0825/items/761fa88ed8da83a967c7)
- Go言語を学習し始めて、簡単なCRUDアプリをクリーンアーキテクチャで作成するまで②←**今ココ**
- [Go言語を学習し始めて、簡単なCRUDアプリをクリーンアーキテクチャで作成するまで③ - Qiita](https://qiita.com/fukubaka0825/items/b79e97cf709a249c13a5)

## はじめに
こちらの記事は前回[Go言語を学習し始めて、簡単なCRUDアプリをクリーンアーキテクチャで作成するまで① - Qiita](https://qiita.com/fukubaka0825/items/761fa88ed8da83a967c7)の続きとなります。
[Go言語を学習し始めて、簡単なCRUDアプリをクリーンアーキテクチャで作成するまで②｜Wano Group Developers Blog](https://developers.wano.co.jp/1948/)にあげたものと同じものになります。

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

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

## ②簡単なCRUDのWebアプリケーション作成
### 1.まずgoenvとdep導入
[Gopkg.toml · dep](https://golang.github.io/dep/docs/Gopkg.toml.html)
[Golangをgoenvを使ってインストールしてみた - Qiita](https://qiita.com/walkers/items/761b2a5e58849176a633)
[goenvでgoをインストール 〜初心者向け〜 - Qiita](https://qiita.com/yut-kt/items/9f5ac1e788df61f64290)
[依存関係管理ツールdep(golang) - Qiita](https://qiita.com/Azizjan/items/66564b5dc7597717932b)

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

### 2.echoでRESTAPI作る 
[【go】echoでapiサーバーを実装するときに最低限必要そうなことをまとめておく - とりあえずphpとか](http://kimagureneet.hatenablog.com/entry/2017/12/20/163848)
[Go の echo ってWebサーバーでサクッと REST しちゃう - Qiita](https://qiita.com/ezaki/items/62e806ae42828bb3567a)

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

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

### 3.DB導入　Gorm使い方覚える
[Mac へ MySQL を Homebrew でインストールする手順 - Qiita](https://qiita.com/hkusu/items/cda3e8461e7a46ecf25d)
[GoでMySQLに接続する - Qiita](https://qiita.com/taizo/items/54f5f49c6102f86194b8)
[【GORM】Go言語でORM触ってみた - Qiita](https://qiita.com/chan-p/items/cf3e007b82cc7fce2d81)
[GoのORマッパーでJoinデータのとり方を学ぶ！ - イノベーション　エンジニアブログ](http://tech.innovation.co.jp/2018/05/19/Go-O-R-Join.html)

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

### 4.CRUDアプリ作成

[Go言語のWebフレームワーク「Echo」を使ってみる ①（Hello World的な） - Qiita](https://qiita.com/y_ussie/items/ca8dc5e423eec318a436)
[Go言語のWebフレームワーク「Echo」を使ってみる ②（リクエストパラメータの扱い） - Qiita](https://qiita.com/y_ussie/items/2d397e70bfc38f75ca51)
[Go言語 - HTMLテンプレートの使い方 - 覚えたら書く](https://blog.y-yuki.net/entry/2017/07/04/100000)
[golang : template の range で index を使う - i++](http://increment.hatenablog.com/entry/2016/04/27/203810)

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

そうしてざっくり作ったのがこちらになります。
[GitHub - takafk9/echo_crud](https://github.com/takafk9/echo_crud)


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

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


@y_ussieさんの実装[Go言語のWebフレームワーク「Echo」を使ってみる ②（リクエストパラメータの扱い） - Qiita](https://qiita.com/y_ussie/items/2d397e70bfc38f75ca51)をかなり参考にしました。(大感謝)

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


```go: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に都度マージして、返すようにしました。

```go: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】 - 技術向上](https://tech-up.hatenablog.com/entry/2018/12/13/112710)

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

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

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

**ではまた次回！！！！**
 == 追記 ==
③を投稿しました！以下のリンクからお読みください！
[Go言語を学習し始めて、簡単なCRUDアプリをクリーンアーキテクチャで作成するまで③ - Qiita](https://qiita.com/fukubaka0825/items/b79e97cf709a249c13a5)