Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
-
Upload
shoot-morii -
Category
Technology
-
view
13.683 -
download
5
description
Transcript of Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
Go言語入門者が
Webアプリケーション を作ってみた話
@GDG Kyoto Dev Fest 2014 Pasta-K
bit.ly/150ijMh
自己紹介• Pasta-K
• Twitter / GitHub : @pastak
• Blog : http://pastak.hatenablog.com
• 京都大学工学部情報学科2回生
• オープンソースカンファレンス京都実行委員
• Go言語歴2ヶ月くらい
で、誰?
京大マイコンクラブ広報
学祭期間中(~月曜日)• 部員の作ったゲーム・音楽の展示
• 某白い犬の会社から来たスペシャルゲストがいます
昨年春 NHKのインタビューを受けた
たまこラブストーリー良かった
本日!!
たまこ役 洲崎綾
トークショー in 京都大学
落選したので来ました
がんばろう
Question
Go言語を
聞いたことがある
書いたことがある
Webアプリを 書いたことがある
🎯Main Target🎯
Go言語を
聞いたことがある
書いてみたい
(PerlとかRubyで)
Webアプリを 書いたことがある
方々
話さないこと 🙊• Go言語の導入方法
• Go言語の文法
• Go言語のイイトコ
• Webアプリケーションのテスト
• Webアプリケーションを作るうえでのベストプラクティス
話すこと 👏
• 自分がGo言語を書いてみようと思い立って書いてみた方法を紹介します
• 有識者の皆様におかれましては「もっと良いのがあるよ」ってことがあれば後でこっそり教えて下さい 🙇
• これからGo言語でWebアプリケーションを書きたい人のとっかかりになれば幸いです
話すこと• HTTPサーバを立ち上げる
• Viewを実装する
• Templateを利用する
• MySQLを利用する
• パッケージマネージャ
目標
とにかくWebアプリを それっぽく作る
とにかくpackageを利用して
Webアプリをそれっぽく作る
今回の構成• Web Application Framework
• goji • Template Engine
• ace • MySQL ORM
• gorp • MySQL Migration
• goose • Package Manager
• gom
1. HTTPサーバを立ち上げる
http packageを利用するpackage main !import "http" !func main() { http.HandleFunc("/", someFuncName) err := http.ListenAndServe(":9090", nil) if err != nil { panic(err) } }
localhost:9090 で起動
github.com/zenazn/goji
特徴(所感)
かなり薄めのWAF 面倒見てくれるのはルーティングくらい `http/net`との親和性
– github.com/zenazn/goji
“Goji first of all attempts to be simple. It is of the Sinatra and Flask school of web
framework design, and not the Rails/Django one.”
さっきのをGojiで書いてみる
package main !import ( "github.com/zenazn/goji" "github.com/zenazn/goji/web" "net/http" ) !func main() { goji.Get("/", someFuncName) goji.Serve() }
GETとかPOSTとかpackage main !import ( "github.com/zenazn/goji" "github.com/zenazn/goji/web" "net/http" ) !func main() { goji.Get("/", Index) goji.Get("/form", Form) goji.Get("/form/", http.RedirectHandler("/event/", 301)) goji.Post("/form/validate", Validate) goji.Serve() }
Hello Worldを出してみるpackage main !import ( "fmt" "github.com/zenazn/goji" "github.com/zenazn/goji/web" "net/http" ) !func hello(c web.C, w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, world") } !func main() { goji.Get("/hello", hello) goji.Serve() }
demo01
Sinatra style URL patternpackage main !import ( "fmt" "github.com/zenazn/goji" "github.com/zenazn/goji/web" "net/http" ) !func hello(c web.C, w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %s!", c.URLParams["name"]) } !func main() { goji.Get("/hello/:name", hello) goji.Serve() }
demo02
2. Viewの実装
Templateの利用
Go言語の標準packageを使うpackage main !import ( "fmt" "net/http" "html/template" ) !type Member struct { Name string Message string } !func main() { http.HandleFunc("/", handler) } !func handler(w http.ResponseWriter, r *http.Request) { member := Member{"pastak", "こんにちは"} var t = template.Must(template.ParseFiles("template.html")) if err := t.Execute(w, member); err != nil { fmt.Println(err.Error()) }
main.go
Go言語の標準packageを使う
<h1> hello {{.Name}} </h1> <p>{{.Message}}</p>
template.html
demo03
if-else<h1> hello {{.Name}} </h1> <p> {{if .IsMorning}} おはようございます!!!!!!!!! {{else}} こんにちは {{end}} </p>
ifの中ではboolしか使えない (`html/template`の場合)
<h1> hello {{.Name}} </h1> <p> <!-- 条件判断は出来ない --> {{if .Name == "John"}} You are John!!!!! {{else}} Who are you? {{end}} </p>
`text/template`はifの中で比較が出来る
<h1> hello {{.Name}} </h1> <p> {{if eq .Name "John"}} You are John!!!!! {{else}} Who are you? {{end}} </p>
for-loop ( range )type Person struct { Name string Email string } !func main() { http.HandleFunc("/", handler) } !func handler(w http.ResponseWriter, r *http.Request) { people := []*Person{ &Person{"john", "[email protected]"}, &Person{"mike", "[email protected]"}, } var t = template.Must(template.ParseFiles("template.html")) _ = t.Execute(w, people) }
main.go
for-loop ( range )<h1> Guest List </h1> <ul> {{range .}} <li>Name: {{.Name}}</li> <ul> <li>Email : {{.Email}}</li> </ul> {{end}} </ul>
template.html
demo04
github.com/yosssi/ace
特徴(所感)
Slimっぽく書ける
“html/template”を利用している
{{if eq .Hoge “hoge”}}できない
– github.com/yosssi/ace
“Ace is an HTML template engine for Go. This is inspired by Slim and Jade.”
Syntex example
= doctype html html lang=en head title Hello Ace = css h1 { color: blue; } body h1#title {{.Title}} p.message {{.Message}}
<!DOCTYPE html> <html lang=en> <head> <title> Hello ace</title> <style> h1 { color: blue; } </style> </head> <body> <h1 id="title">TitleText</h1> <p class=“message">Messages</p> </body> </html>
使ってみるfunc handler(w http.ResponseWriter, r *http.Request) { tpl, err := ace.Load("example", nil, nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if err := tpl.Execute(w, map[string]string{"Msg": "Hello Ace"}); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } }
main.go
使ってみる
= doctype html html lang=en head title Ace example body h1 {{.Msg}}
example.ace
demo(時間があれば)
3. MySQLを利用する
出来れば、あんまり生のSQLは書きたくない・・・
そうだ
ORM
github.com/coopernurse/gorp
gorpについて• MySQL, PostgreSQL, sqlite3
• ここではMySQLの例で説明します
• 極力SQLを書かずにDBを扱える
table name: people
name Type Null
id Int Not Null Primary Key
name String Not Null
Email String Null
DBのカラムを表す 構造体を定義
type Person struct { Id int32 Name string Email sql.NullString // Nullを許容する場合はsql.Null****型を指定 }
データベースマッパーを作って 構造体と紐付ける
db, _ := sql.Open("mymysql", "tcp:localhost:3306*dbName/user/passwd") dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", “UTF8"} } t1 := dbmap.AddTableWithName(Person{},”people") .SetKeys(true, "Id") t1.ColMap("Id").Rename("id") t1.ColMap("Name").Rename("name") t1.ColMap("Email")
Select
var people []Person dbmap.Select(&people, "select * from people order by id") // Select single row var person Person dbmap.SelectOne(&person, "select * from people where id=?", id) // Select by primary key obj, err := dbmap.Get(Person{}, 5) p := obj.(*Person)
Update / Insert / Deletealice := &Person{ 0, "Alice",sql.NullString{"[email protected]", true} } err := dbmap.Insert(alice) !alice2 := &Person{ 0, "Alice", sql.NullString{"[email protected]", true} } count, err := dbmap.Update(alice2) !alice := &Person{1} count, err := dbmap.Delete(alice)
Migration
bitbucket.org/liamstask/goose
dbディレクトリを作成
$ mkdir db$ cd db
設定ファイルを書く
development: driver: mymysql open: dbname/user/password!production: driver: mymysql open: dbname/user/password
db/dbconf.yml
サンプル $GOPATH/src/bitbucket.org/liamstask/goose/db-sample/dbconf.yml
設定の確認 Migrationの作成
$ goose statusgoose: status for environment 'development'$ goose create myapp sql
db/migration/YYYYMMDDhhmmss_myapp.sql !が生成される
Migration用ファイルの編集-- +goose Up -- SQL in section 'Up' is executed when this migration is applied CREATE TABLE IF NOT EXISTS `people`( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR() NOT NULL, `Email` VARCHAR() PRIMARY KEY (`id`)) ENGINE = InnoDB; !-- +goose Down -- SQL section 'Down' is executed when this migration is rolled back DROP TABLE `people`;
db/migration/YYYYMMDDhhmmss_myapp.sql
Migrationの実行$ goose up
Rollback
$ goose down
4. パッケージマネージャを利用する
github.com/mattn/gom
ポイント• RubyのBundleっぽい操作感で使える
– github.com/mattn/gom
“The `go get` command is useful. But we want to fix the problem where package
versions are different from the latest update. Are you going to do go get -
tags=1.1 ..., go get -tag=0.3 for each of them? We want to freeze package
version. Ruby's bundle is awesome.”
Gomfileを編集gom 'github.com/zenazn/goji' gom 'github.com/zenazn/goji/web' gom 'github.com/yosssi/ace' gom 'github.com/coopernurse/gorp' gom 'bitbucket.org/liamstask/goose/cmd/goose' gom 'github.com/ziutek/mymysql/thrsafe' gom 'github.com/ziutek/mymysql/autorc' gom 'github.com/ziutek/mymysql/godrv'
Gomfile
Gomfileを編集!gom 'github.com/yosssi/ace', :tag => 'tag_name' gom 'github.com/yosssi/ace', :branch => 'branch_name' gom 'github.com/yosssi/ace', :commit => 'commit_id'
Gomfile
gom install$ gom installinstalling …installing …$ ls _vendor_vendor"## bin$ &## goose"## pkg$ &## darwin_amd64&## src "## bitbucket.org $ &## liamstask "## code.google.com &## github.com
run & build$ gom exec go run main.go// `go run` with packages$ gom build// `go build` with packages
$ gom exec _vendor/bin/goose create myapp sql
🎉まとめ🎉• goji / ace / gorp with gom and goose なWebアプリケーションを作ってみる方法をざっと紹介しました
• 作ってみたときのやつをGitHubに上げておくので良かったら参考にしてみてください
• (まだ上がってないので、上げたらブログに書きます)
• もっと良い知見がある人は是非教えて下さい!
参考URLなど• Golang でのウェブ開発を考えてみる
• http://qiita.com/voluntas/items/7af2f06d2688f649576f
• astaxie/build-web-application-with-golang
• https://github.com/astaxie/build-web-application-with-golang/tree/master/ja
• golang製のDBマイグレーションツールgooseをMySQLで使ってみる
• http://shusatoo.net/programming/golang/goose-mysql-migration/
• Keynote Template: Azusa
• http://memo.sanographix.net/post/82160791768