SlideShare a Scribd company logo
Go言語入門者が 
Webアプリケーション 
を作ってみた話 
@GDG Kyoto Dev Fest 2014 
Pasta-K 
pastak@kmc.gr.jp
bit.ly/150ijMh
自己紹介 
• Pasta-K 
• Twitter / GitHub : @pastak 
• Blog : http://pastak.hatenablog.com 
• 京都大学工学部情報学科2回生 
• オープンソースカンファレンス京都実行委員 
• Go言語歴2ヶ月くらい
で、誰?
京大マイコンクラブ広報
学祭期間中(~月曜日) 
• 部員の作ったゲーム・音楽の展示 
• 某白い犬の会社から来たスペシャルゲストが 
います
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
昨年春 
NHKのインタビューを受けた
Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto
たまこラブストーリー良かった
本日!!
たまこ役 洲崎綾 
トークショー 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`との親和性
“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.” 
– github.com/zenazn/goji
さっきのを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 pattern 
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, %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 ) 
main.go 
type Person struct { 
Name string 
Email string 
} 
! 
func main() { 
http.HandleFunc("/", handler) 
} 
! 
func handler(w http.ResponseWriter, r *http.Request) { 
people := []*Person{ 
&Person{"john", "john@example.com"}, 
&Person{"mike", "mike@example.com"}, 
} 
var t = template.Must(template.ParseFiles("template.html")) 
_ = t.Execute(w, people) 
}
for-loop ( range ) 
<h1> Guest List </h1> 
<ul> 
{{range .}} 
template.html 
<li>Name: {{.Name}}</li> 
<ul> 
<li>Email : {{.Email}}</li> 
</ul> 
{{end}} 
</ul> 
demo04
github.com/yosssi/ace
特徴(所感) 
Slimっぽく書ける 
“html/template”を利用している 
 {{if eq .Hoge “hoge”}}できない
“Ace is an HTML template engine for 
Go. This is inspired by Slim and Jade.” 
– github.com/yosssi/ace
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 / Delete 
alice := &Person{ 
0, "Alice",sql.NullString{"alice@example.com", true} 
} 
err := dbmap.Insert(alice) 
! 
alice2 := &Person{ 
0, "Alice", sql.NullString{"alice@alice.net", 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 status 
goose: status for environment 'development' 
$ goose create myapp sql 
db/migration/YYYYMMDDhhmmss_myapp.sql 
!が生成される
Migration用ファイルの編集 
db/migration/YYYYMMDDhhmmss_myapp.sql 
-- +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`;
Migrationの実行 
$ goose up 
Rollback 
$ goose down
4. パッケージマネージャを利 
用する
github.com/mattn/gom
ポイント 
• RubyのBundleっぽい操作感で使える
“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.” 
– github.com/mattn/gom
Gomfileを編集 
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'
gom install 
$ gom install 
installing … 
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
Thank you  
pastak@kmc.gr.jp

More Related Content

Go言語入門者が Webアプリケーション を作ってみた話 #devfest #gdgkyoto