Contenu connexe Similaire à GoによるWebアプリ開発のキホン (20) Plus de Akihiko Horiuchi (20) GoによるWebアプリ開発のキホン6. GoでWebアプリを開発する メリット
● インタプリタと比較して 高速・軽量
○ Railsより50倍の速度と10倍の省メモリという話も[1]
● 並列処理 が簡単
○ goroutine(スレッド)と channel(メッセージパッシング)
○ go func() のように go を使うだけ
● シングルバイナリ でデプロイ
○ コンパイルしたバイナリをアップロードするだけ
○ ライブラリのインストールなどが不要
○ コンテナ や マイクロサービス との親和性が高そう
16/02/27 6
[1] https://plus.google.com/+MattAimonetti/posts/PeZk8FY3PWY
7. GoでWebアプリを開発する メリット
● コーディング規約 を統一
○ gofmt(goimports)で強制的に直される
○ 可読性が上がる、チーム開発がスムーズになる
● 標準でテストをサポート
○ 関数をテストする関数を *_test.go に書く
○ あとは go test で実行するだけ
16/02/27 7
func TestSum(t *testing.T) {
actual := Sum(10, 20)
expected := 30
if actual != expected {
t.Fatal("want", expected, "got", actual)
}
}
10. Goの 動物図鑑 が出ました
○ チャットアプリの作成
○ WebSocket、OAuth
○ コマンドラインツールの作成
○ ミドルウェアとの連携
○ Twitter、Googleとの連携
○ REST APIの公開
○ Goの開発環境構築
などなど
基本を押えた内容で
これからGoでWebアプリを
開発する人にオススメ
16/02/27 10
11. 必要な コト 、考える コト
● Webアプリケーションフレームワーク
○ RubyならRails、PythonならDjango、Goは?
○ デザインパターンは Model・View・Controller ?
● データベース周りのコト
○ マイグレーションツールは?( rake db:migrate とか)
○ ORマッパーは?(ActiveRecordとか)
● Viewは? テンプレートエンジンは?
○ 標準で "text/template" と "html/template" が付属
○ でも Slim とか Haml とか使いたい
16/02/27 11
14. "net/http" のキホン
● シンプルなWebサーバを作る
○ http.HandleFunc でルーティングを定義
(ただし "/users/:id" のようにパラメタは取れない)
○ http.ListenAndServe でWebサーバを起動
○ ログ出力は "log" を使って自分で書く
16/02/27 14
func main() {
http.HandleFunc("/",
func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, World!")
log.Printf("%+vn", r)
}
)
http.ListenAndServe(":8080", nil)
}
15. Webアプリフレームワーク
● GoのWebアプリフレームワークは 戦国時代
○ まだデファクトスタンダードが決まってない
○ シンプル なモノから フルスタック なモノまで[2]
○ "net/http" をベースに機能を拡張したものが多い
16/02/27 15
シンプル
(ルーティングのみ)
フルスタック
(セッションなど)
github.com/zenazn/goji
github.com/gin-gonic/gin
github.com/gorilla/mux
github.com/revel/revel
[2] http://qiita.com/najeira/items/bdc988c4e93b3b5ccf2f
16. Webアプリフレームワーク
● Goji( github.com/zenazn/goji )
● Gorilla( github.com/gorilla/mux )
16/02/27 16
router := goji.New()
router.Get("/:name", handler)
func handler(c goji.C, w http.ResponseWriter, r ...) {
name := c.URLParams["name"]
fmt.Fprintf(w, "Hello, %s!n", name)
}
router := gorilla.NewRouter()
router.HandleFunc("/{name}", handler)
func handler(w http.ResponseWriter, r *http.Request) {
name := gorilla.Vars(r)["name"]
fmt.Fprintf(w, "Hello, %s!n", name)
}
17. GoでDBのマイグレーション
● goose( bitbucket.org/liamstask/goose )
○ マイグレーション:DBのバージョン管理のこと
(テーブルの作成、カラムの追加、ロールバックなど)
○ マイグレーションのスクリプトは SQL かGoで書く
○ create 、up 、down コマンドを使って管理
16/02/27 17
$ goose create create_posts
goose: created db/migrations/20160226202023_create_posts.sql
$ goose up
goose: migrating db environment 'development', ...
OK 20160226202023_create_posts.sql
$ goose down
goose: migrating db environment 'development', ...
OK 20160226202023_create_posts.sql
18. gooseのマイグレーションファイル
● マイグレーションファイルのサンプル
○ up・down に対応するSQLスクリプトを書く
○ Goで書く場合は sql.Tx.Exec でSQLを実行
○ IDの AUTO_INCREMENT や PRIMARY KEY の設定を忘れずに
16/02/27 18
-- +goose Up
-- SQL in section 'Up' is executed when this migration is ...
CREATE TABLE IF NOT EXISTS `posts` (
`id` INT NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOT NULL,
`body` TEXT NOT NULL,
PRIMARY KEY (`id`)
);
-- +goose Down
-- SQL section 'Down' is executed when this migration is ...
DROP TABLE `posts`;
19. DBから構造体にマッピング
● ORM(Object-Relation Mapping)
○ DBのタプルをGoの 構造体 に変換するもの
○ WAFと同じく シンプル なモノと フルスタック なモノ
○ マイグレーションもできるものが多い
16/02/27 19
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
type User struct {
gorm.Model
Name string
}
20. ORマッパーのサンプル
● GORM( github.com/jinzhu/gorm )
○ かなり 高機能 でActiveRecordに近い使用感
○ First などの便利な関数、クエリの連鎖も可能
● genmai( github.com/naoina/genmai )
○ 機能はシンプルでクエリビルダに近い
16/02/27 20
db.CreateTable(&User{})
user := User{Name: "Kagawa"}
db.Create(user)
db.Where(&User{Name: "Kagawa"}).First(&user)
db.CreateTable(&User{})
user := User{Name: "Kagawa"}
db.Insert(&user)
db.Select(&users, db.Where("name", "=", "Kagawa"))
21. "html/template" のキホン
● テンプレートを使うハンドラーを作る
○ 構造体 をテンプレートに渡して {{}} で展開
○ template.ParseFiles でファイル読み込みも可能
type Page struct {
Name string
}
func handler(w http.ResponseWriter, r *http.Request) {
tmpl, _ := template.New("tmpl").Parse("Hello, {{.Name}}!")
tmpl.Execute(w, Page{Name: "Golang"})
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
16/02/27 21
22. テンプレエンジン Ace を使う
● Ace( github.com/yosssi/ace )
○ SlimやJadeにインスパイアされてる
○ ace.Load すると *template.Template が返ってくる
○ 部分テンプレートにも対応( render partial 的な)
16/02/27 22
= doctype html
html lang=en
head
title Hello Ace
= css
.blue { color: blue; }
body
h1.blue {{.Msg}}
p..
Ace is an HTML template engine for Go.
= javascript
console.log('Welcome to Ace');
23. Goのパッケージマネージャ
● Godep( github.com/tools/godep )
○ Godeps.json に従って Godeps/_workspace に保存
○ Herokuなどでも採用され、ほぼスタンダード?
● gom( github.com/mattn/gom )
○ 使い勝手はほぼ Bundler + Gemfile と同じ
○ gom install 、gom exec 、gom build 、など
16/02/27 23
{
"Deps": [{
"ImportPath": "code.google.com/p/go-netrc/netrc",
"Rev": "28676070ab99"
}]
}
24. gom の使い方
● Rubyist なのでgom推し
○ Gomfile を書いて gom install するだけ
○ パッケージをtag、branch、commit で指定可能
○ _vendor ディレクトリにパッケージが保存される
16/02/27 24
gom 'github.com/yosssi/ace'
gom 'github.com/zenazn/goji'
group :development do
gom 'github.com/pilu/fresh'
gom 'golang.org/x/tools/cmd/goimports'
end
$ gom install
downloading github.com/google/go-github/github
downloading github.com/yosssi/ace
...
25. ビルドツールで快適に開発
● Fresh( github.com/pilu/fresh )
○ ソースコードの変更を検知してリビルド
○ 変更の反映にコンパイルが必要なGoの強い味方
○ JavaScriptだとGrantとかgulpみたいな感じ?
○ 監視する拡張子と間隔を設定できる
16/01/23 25
$ gom exec fresh -c runner.conf
Loading settings from runner.conf
22:7:30 runner | InitFolders
22:7:30 runner | mkdir ./tmp
22:7:30 runner | mkdir ./tmp: file exists
22:7:30 watcher | Watching .
22:7:30 watcher | Watching app
22:7:30 watcher | Watching app/controllers
22:7:30 watcher | Watching app/views
27. 今回のポイント・工夫
● GojiでMVCデザインのAPIサーバを作成
○ これまでRails + Grapeで開発していたので
○ Viewはヘッダー・ナビゲーションバー・フッターのみ
● フロントエンドはMithril.jsで作成
○ MVCデザインのJavaScriptフレームワーク
○ 仮想DOM 採用で、Reactよりも 高速・軽量
○ モデルはAPIから返ってきたJSONをそのまま使う
○ ソースコードはバイナリ化してGinで配信
バックエンドはGoで最速のフレームワーク
フロントエンドもJavaScriptで最軽量のフレームワーク
16/01/23 27
29. GoでJSONなRESTful API
● GoでJSONを使うのはカンタン
○ 雛形になる 構造体 を定義してエンコード・デコード
○ HTTPハンドラのBodyでJSONを書き込めばOK
○ GojiとGORMを使った場合のイメージ
16/02/27 29
router := goji.New()
router.Get("/api/users/:name", handler)
func handler(c goji.C, w http.ResponseWriter, r ...) {
var user User
name := c.URLParams["name"]
db.Where(&User{Name: name}).First(&user)
bytes, _ := json.Marshal(user)
fmt.Println(w, string(bytes))
w.Header.Set("Content-Type", "application/json")
}
31. yosage
Web application of LGTM gif generator
http://yosage.hiconyan.com/
https://github.com/hico-horiuchi/yosage
16/01/23 31
33. まとめ
● GoでWebアプリを開発するメリット
○ 高速・軽量、並列処理、デプロイ、規約、テスト
○ バックエンド( API )での採用が多い
● MVCデザインで考える
○ Model :Goの 構造体 と ORマッパー で定義
○ View :標準の "html/template" で十分、Aceも
○ Controller:HTTPのハンドラとして実装
● 完成までに必要なこと
○ 認証( OAuth など)、セッション(Cookie)
○ セキュリティ対策(CSRF、SQLインジェクション)
16/02/27 33