Web アプリケーションを書くときは今までずっと
というスタンスを何故か貫いて来たんだけど、最近ようやく web.go をやめて goji を使う様になった。
Goji
A web microframework for Golang
https://goji.io/
理由としては
- Sinatra ライクでありながら高度な正規表現マッチも使えるルータ
- それでいて net/http コンパチ
- 簡単に実装出来るミドルウェアスタック
- グレースフルシャットダウン
- そして何と言っても速い
ミドルウェアも一般的な Web アプリケーションを作るには十分な物が既に揃ってます。
それでもやっぱり大きめな物は net/http で書くんだけど、小規模から中規模な物を一気にゴリゴリっと書く場合には goji は便利です。もちろん Windows でも動きます。
今日はこの goji と pongo2 というテンプレートエンジン、そして naoina さんが開発している ORM の genmai を使って Wiki を作ってみたいと思います。
ORM には genmai を使います。
おれのかんがえたさいきょうの ORM for Golang - 何気に大変
http://naoina.plog.la/2014/02/17/121743410109
naoina/genmai - GitHub
package main import ( "database/sql" "fmt" "time" _ "github.com/mattn/go-sqlite3" // _ "github.com/g...
https://github.com/naoina/genmai
genmai、とても便利です。フォルダ構成はルートにアプリケーション、view ディレクトリにテンプレート、assets に静的ファイルを置きます。テンプレートエンジンには pongo2 を使います。pongo2 は jedie でも使っています。
genmai を食す際の構造体は以下の通り。
type Page struct {
Id int64 `db:"pk"`
Title string `db:"unique" json:"title"`
Body string `json:"body"`
URL string `db:"-"`
Deleted bool `json:"deleted"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
SQLite3 のダイアレクトを指定して Page テーブルを作ってもらいます。
db, err := genmai.New(&genmai.SQLite3Dialect{}, "./wiki.db")
if err != nil {
log.Fatalln(err)
}
if err := db.CreateTableIfNotExists(&Page{}); err != nil {
log.Fatalln(err)
}
Wiki なのでルーティングは以下の通り。
- 静的ファイル
/assets
, GET - ページ一覧
/
, GET - ページ
/wiki/:title
, GET - 編集画面
/wiki/:title/edit
, GET - 更新処理
/wiki/:title
, POST
goji だと以下の様に登録します。
goji.Get("/assets/*", http.FileServer(http.Dir(".")))
goji.Get("/", showPages)
goji.Get("/wiki/:title", showPage)
goji.Get("/wiki/:title/edit", editPage)
goji.Post("/wiki/:title", postPage)
ページの表示処理は以下の様にしました。
func showPage(c web.C, w http.ResponseWriter, r *http.Request) {
wiki := getWiki(c)
db := wiki.DB
var pages []Page
err := db.Select(&pages, db.From(&Page{}), db.Where("title", "=", c.URLParams["title"]))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
var page Page
if len(pages) > 0 {
page = pages[0]
}
if page.Title == "" {
page.Title = c.URLParams["title"]
}
page.URL = wiki.PageURL(&page)
tpl, err := pongo2.DefaultSet.FromFile("page.tpl")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tpl.ExecuteWriter(pongo2.Context{"page": page}, w)
}
そしてテンプレート view/page.tpl
は以下の通り。pongo2 はテンプレートのキャッシュに対応しているので処理が書けたら起動したままテンプレートファイルを編集する事が出来てとても便利です。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ page.Title }}</title>
<link rel="stylesheet" href="/assets/css/style.css" media="all">
</head>
<body>
<div id="content">
<h1 class="title">{{ page.Title }}</h1>
<div class="body">
{{ page.Body | markdown }}
</div>
<span class="date">Updated at: {{ page.UpdatedAt | date: "2006/01/02 03:04:05" }}</span>
<br />
<a href="{{ wiki.URL }}">Page index</a>
<a href="{{ page.URL }}/edit">Edit this page</a>
</div>
</body>
</html>
編集画面や登録処理も同様の手順で作ると、以下の様な Wiki ページが出来上がります。
ソースコードは以下に置いておきます。興味のある方はどうぞ。
mattn/goji-wiki - GitHub
https://github.com/mattn/goji-wiki