· Advent Calendar golang Go言語 MySQL net/http/fcgi template

#golang でマッチングサイトを作った時の感想。

  • このエントリーをはてなブックマークに追加

この記事は Go Advent Calendar 2013 の 18 日目の投稿です。

はじめに

今年もいろいろと行われていますAdvent Calendarですが、初めて参加させて頂きます。プログラミング界隈のプロフェッショナルな方々の中で書くというのは、ただ1人で家で書いてるだけなのに、ちょっと緊張しちゃってます(^^ゞ 

簡単にGo歴を。2012年1月に勉強会に参加してから、シンプルで守備範囲が広そうで強力で、なにより楽しいと感じ、それから自分で勉強したりして発表させて頂いたりしました(slideshare)。神戸からGoCon Springに参加したり、神戸から名古屋の勉強会に参加したりしました。

そんな中、今年の10月に、マッチングサイトを作ってほしいという話があり、言語は何でもいいとのことだったので、担当者に”Goはキマスよ”と訴え続け、Goで作らせて頂きました。

そこで、よく「Goで何ができるの?」って聞かれますので、「マッチングサイトが作れますよ」という事例を紹介したいところなのですが、そのマッチングサイトは、まだオープンしておらず、残念ながらリンクやスクリーンショットを貼ることができません。ので、そのマッチングサイトを作った時の”機能”と”構成”を簡単に説明した後、”感想”を書いていきたいと思います。

機能

このマッチングサイトのおおまかな機能としては、以下になります。

マッチングサイトの必要最低限の機能のイメージです。

構成

サーバーの構成

Nginx + Golang(FastCGI) + MySQLで作成しました。

パッケージ構成

mainパッケージの他にdbパッケージ、dataパッケージ、後はテンプレートファイル(*.tmpl)です。

MVCモデルのイメージで言うと、data,dbパッケージがModelで、テンプレートはView、mainパッケージがControllerというイメージで作成しました。あとは、utilパッケージです。もちろん、db,data,utilという名前である必要はありません。

各パッケージのファイル数と総ステップ数

使用した外部ライブラリ

データベース関連

画像関連

実績工数

実装2人で約30人日(デザイン除く)

感想

(これだけではイメージ沸かないですよね・・・すみません。。。感想に入らせて頂きます。)

●現在、Revelと先日の海外のAdvent Calenderで発表がありましたbeegoというフレームワークがありますが、このくらいの規模ならフレームワークは不要かなと思いました。

●ORMのgorpを使わず、ゴリゴリSQLをかいても出来ますが、gorpにより非常に楽させてもらいました。個人的には使いやすかったと思います。

●標準パッケージでテンプレート(html/template)が使え、改めてフレームワークなどを入れる必要がないので、余計な使い方を覚える必要がないのが個人的には良いと思いました。

●デザイン部分はデザイナーさんが担当したのですが、if文などのプログラミングがわかならなくても、”{{}}部分はプログラムしていますが、他のところはいじってもらって大丈夫です”ぐらいの説明で、テンプレートファイルを容易に理解して頂いたので、楽でした。

{{define "header"}}ヘッダー{{end}}のようにモジュール化でき、{{template "header"}}のようにして、モジュールを呼び出すことが出来ますが、あたりまえかもしれませんが、これもやみくもにモジュール化するのではなくて、分かりやすい構成にした方がよいと感じました。

●テンプレートファイルの読み込みの仕方によっては、Goのバイナリを再コンパイルしなくても更新されるのは、非常に重宝しました。デザイナーさんがデザインを変更しても、ブラウザの更新だけでデザインの変更が確認できるからです。

このようにする読み込みの仕方は、テンプレートファイルをParseするときに、関数の外で読み込まないことです。

func RootHandler(w http.ResponseWriter, r *http.Request) {
    tmpl := template.New("main.tmpl")
    tmpl = template.Must(tmpl.ParseGlob("templates/*.tmpl"))
    data = ・・・
    tmpl.Execute(w,data)
    ・・・
}

つまり、次のようにしてしまうと、ブラウザの更新だけでは更新されません。

var  tmpl = template.Must((template.New("main.tmpl")).ParseGlob("templates/*.tmpl"))

func RootHandler(w http.ResponseWriter, r *http.Request) {
    data = ・・・
    tmpl.Execute(w,data)
    ・・・
}

●Go1.2からテンプレートに比較演算子が使えるようになりましたが(本家変更点, 翻訳)、個人的にはテンプレートをあまりプログラムちっくにすべきではないかもしれないと思いました。デザイナーさんにやさしいテンプレートを作成することが関係を良くするポイントかもしれません。

●(感想というか覚え書きですが)テンプレートでは、ある構造体にレシーバとして定義したメソッドが使えます(text/templateパッケージ)。

例えば、

type Person struct{
    Address int
}

func (p *Person) Method() bool {
    ・・・・
} 

としたとき、テンプレートファイルを、

{{if .Method}}
・・・
{{end}}

とすれば、Methodが使えます。template.FuncMap(使い方)は、データに紐付けなくてもよい関数を作り、データに関連するものは上記のMethodのように作るようにすれば分かりやすいかなと思います。

●(これも感想というか覚え書きですが)fcgi.Serve関数内で、要求があるたびに新しくゴルーチンを作っています(ソース)。

終わりに

このマッチングサイトのリンクやスクリーンショットを示せず、とても分かりにくかったと思いますが、”Goってツール系のイメージがある”とか、”速さが必要なところでしか使わない”とか思ってる方に、普通にWebサイトが作れるんだ、ということを少しは知って頂けたかなと思い、終わりにしたいと思います。

なにかGoに関してご相談ありましたら、[@kwmt27][1] までご連絡下さい。最後までお読み頂きありがとうございました。

[1]: https://twitter.com/kwmt27

  • このエントリーをはてなブックマークに追加
  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket