Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
How to create a Web
application for Golang
@yosuke_furukawa
@yosuke_furukawa
Node.jsユーザーグループ代表 / DeNA所属
Golang歴:2ヶ月くらい
作ったもの
!
- socket.io-go-emitter
- golang + angularjs で chat sample
- qiita アドベントカレンダーをスクレイピングす
るツール
Webアプリの作り方
Webアプリの作り方
net/httpでのwebサーバの建て方
DBアクセス/ORM
Web Application Framework
golangの勉強会を有志の数名
集めてDeNAでやってた
golangの勉強会をDeNAで
やってた
今回の話はそのまとめ
Goでweb applicationを
作る時に知っておいた方が
良いこと
net/httpでWebサーバをたててみる
https://gist.github.com/yosuke-furukawa/8309096
net/httpでWebサーバをたてる
package main	
!
import (	
"fmt"	
"net/http"	
"log"	
)	
!
func hello(w http.ResponseWriter, r *http.Req...
net/httpでWebサーバをたてる
package main	
!
import (	
"fmt"	
"net/http"	
"log"	
)	
!
func hello(w http.ResponseWriter, r *http.Req...
ListenAndServeの動き
func (srv *Server) Serve(l net.Listener) error {	
defer l.Close()	
var tempDelay time.Duration // how lo...
ListenAndServeの動き
func (srv *Server) Serve(l net.Listener) error {	
defer l.Close()	
var tempDelay time.Duration // how lo...
GoでRESTFul APIを作る
RESTFul APIおさらい
各URIがリソースを表す
このリソースを操作するため4つの
HTTPのメソッドを扱う
RESTFul APIおさらい
/users/:id
ユーザーを表現するためのリソース
GET, POST, PUT, DELETE
HTTP methodを使って操作する
RESTFul APIを作る
package main	
!
import (	
"fmt"	
"github.com/drone/routes"	
"net/http"	
)	
!
// GET用のHandler	
func getuser(...
RESTFul APIを作る
package main	
!
import (	
"fmt"	
"github.com/drone/routes"	
"net/http"	
)	
!
// GET用のHandler	
func getuser(...
これだけで簡単なREST APIは作れる
DBアクセス
https://gist.github.com/yosuke-furukawa/8552841
DBアクセス
package main	
!
import (	
"database/sql"	
_ "github.com/go-sql-driver/mysql"	
"log"	
)	
!
func main() {	
  // sql.O...
DBアクセス
package main	
!
import (	
"database/sql"	
_ "github.com/go-sql-driver/mysql"	
"log"	
)	
!
func main() {	
  // sql.O...
SELECT操作
var (	
id int	
name string	
)	
// db.PrepareでPreparedStatement実行	
stmt, err := db.Prepare("select id, name from u...
SELECT操作
var (	
id int	
name string	
)	
// db.PrepareでPreparedStatement実行	
stmt, err := db.Prepare("select id, name from u...
INSERTとかUPDATEとかDELETEとか
!
stmt, err := db.Prepare("INSERT INTO users(id, name) VALUES(?, ?)")	
if err != nil {	
log.Fatal...
INSERTとかUPDATEとかDELETEとか
!
stmt, err := db.Prepare("INSERT INTO users(id, name) VALUES(?, ?)")	
if err != nil {	
log.Fatal...
ここまでで簡単なDBアクセスと永続化はできる
ORM
こんだけある…
http://present.go-steel-programmers.org/talk-review-orms/gsp-go-orms.slide#1
あんまり試せてない…
シンプルでquery builderっぽいgorpか
gormが良さそうだけど、API的には
どれも有意差はない
Web Application Frameworks
https://gist.github.com/yosuke-furukawa/8816249
TL;DR
net/http
martini, beego
revel, falcore
goweb,
drone/routes
gorilla/negroni
need simple
REST Framework
toolkit/compat...
martini
!
• フルスタックフレームワーク
• martiniがsinatraならこっちはRoR, Play
Framework、ちなみに初期ページすごくPlayっぽい
• 中にmail senderやwebsocketも組み込まれてる...
Falcore
• 我らがngmoco製、最近はメンテをfitstarさんに
譲っている様子
• フルスタックフレームワーク
• HUPを送ったら自動でprocessをforkして子プロ
セスがreadyになったら自分を殺す動きをする
• これに...
beego
• revelほど高機能ではないが、一応フルスタックフレームワーク
• ドキュメントが超親切
• beego/ORMをサポートし、MVCに

特化している
• 中国では採用実績あり?
!
!
!
!
!
martini
!
!
• 人気がある(github/star的な意味で)
• すごくSinatra/Expressライク
• 基本的な機能しかコアには存在せず、ミドル
ウェアで機能拡張する
• 豊富なミドルウェアが存在している。
• ただし、...
martini
!
!
• Martiniの作者がHTTP serverをより簡易的に、イディ
オム的に扱えるようにするために開発したライブラリ
• 正確にはフレームワークではなく、ライブラリ群
• 今後Martiniの代わりにスタンダードにな...
martini
!
!
• こちらも正確にはツールキット
• router, secure session, websocket等、まぁWebアプリ作
るには使うよねっていうのが ってる。
• isucon っていうweb アプリ高速化チューニ...
WAFまとめ
net/http
martini, beego
revel, falcore
goweb,
drone/routes
gorilla/negroni
need simple
REST Framework
toolkit/compa...
まとめ
• Webサーバの建て方とnet/httpの

基礎的な話
• DBアクセスの方法
• Web Application Framework

まとめ
今後やりたい事
今後やりたい事
Go + socket.io で死ぬ予定
Upcoming SlideShare
Loading in …5
×

ヒカルのGo 資料 Webアプリケーションの作り方

  • Be the first to comment

ヒカルのGo 資料 Webアプリケーションの作り方

  1. 1. How to create a Web application for Golang @yosuke_furukawa
  2. 2. @yosuke_furukawa Node.jsユーザーグループ代表 / DeNA所属
  3. 3. Golang歴:2ヶ月くらい 作ったもの ! - socket.io-go-emitter - golang + angularjs で chat sample - qiita アドベントカレンダーをスクレイピングす るツール
  4. 4. Webアプリの作り方
  5. 5. Webアプリの作り方 net/httpでのwebサーバの建て方 DBアクセス/ORM Web Application Framework
  6. 6. golangの勉強会を有志の数名 集めてDeNAでやってた
  7. 7. golangの勉強会をDeNAで やってた
  8. 8. 今回の話はそのまとめ
  9. 9. Goでweb applicationを 作る時に知っておいた方が 良いこと
  10. 10. net/httpでWebサーバをたててみる https://gist.github.com/yosuke-furukawa/8309096
  11. 11. net/httpでWebサーバをたてる package main ! import ( "fmt" "net/http" "log" ) ! func hello(w http.ResponseWriter, r *http.Request) { //fmt.Fprintfでwに入るものがクライアントに出力される fmt.Fprintf(w, "Hello World!") } ! func main() { // アクセスのルーティングを設定する http.HandleFunc("/", hello) // portを指定して起動 err := http.ListenAndServe(":9090", nil) if err != nil { log.Fatal("ListenAndServe: ", err) } }
  12. 12. net/httpでWebサーバをたてる package main ! import ( "fmt" "net/http" "log" ) ! func hello(w http.ResponseWriter, r *http.Request) { //fmt.Fprintfでwに入るものがクライアントに出力される fmt.Fprintf(w, "Hello World!") } ! func main() { // アクセスのルーティングを設定する http.HandleFunc("/", hello) // portを指定して起動 err := http.ListenAndServe(":9090", nil) if err != nil { log.Fatal("ListenAndServe: ", err) } } HandleFuncでrouting ListenAndServeでportを指定して起動
  13. 13. ListenAndServeの動き func (srv *Server) Serve(l net.Listener) error { defer l.Close() var tempDelay time.Duration // how long to sleep on accept failure for { rw, e := l.Accept() if e != nil { if ne, ok := e.(net.Error); ok && ne.Temporary() { if tempDelay == 0 { tempDelay = 5 * time.Millisecond } else { tempDelay *= 2 } if max := 1 * time.Second; tempDelay > max { tempDelay = max } log.Printf("http: Accept error: %v; retrying in %v", e, tempDelay) time.Sleep(tempDelay) continue } return e } tempDelay = 0 c, err := srv.newConn(rw) if err != nil { continue } go c.serve() } }
  14. 14. ListenAndServeの動き func (srv *Server) Serve(l net.Listener) error { defer l.Close() var tempDelay time.Duration // how long to sleep on accept failure for { rw, e := l.Accept() if e != nil { if ne, ok := e.(net.Error); ok && ne.Temporary() { if tempDelay == 0 { tempDelay = 5 * time.Millisecond } else { tempDelay *= 2 } if max := 1 * time.Second; tempDelay > max { tempDelay = max } log.Printf("http: Accept error: %v; retrying in %v", e, tempDelay) time.Sleep(tempDelay) continue } return e } tempDelay = 0 c, err := srv.newConn(rw) if err != nil { continue } go c.serve() } } リスナーを通じてリクエストを受け取る 新しくコネクションのinstanceを作る goroutineを起動し、リクエストを処理 ユーザーからのリクエストは全て新しいgoroutine で行われ、互いに影響しない作りになっている
  15. 15. GoでRESTFul APIを作る
  16. 16. RESTFul APIおさらい 各URIがリソースを表す このリソースを操作するため4つの HTTPのメソッドを扱う
  17. 17. RESTFul APIおさらい /users/:id ユーザーを表現するためのリソース GET, POST, PUT, DELETE HTTP methodを使って操作する
  18. 18. RESTFul APIを作る package main ! import ( "fmt" "github.com/drone/routes" "net/http" ) ! // GET用のHandler func getuser(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() id := params.Get(":id") fmt.Fprintf(w, "you are get user %s", id) } // PUT, DELETE, POST用の… ! func main() { mux := routes.New() // GET, PUT, DELETE, POST 用のハンドラー関数をroutingする mux.Get("/users/:id", getuser) mux.Put("/users/:id", modifyuser) mux.Del("/users/:id", deleteuser) mux.Post("/users/", adduser) http.Handle("/", mux) http.ListenAndServe(":9090", nil) }
  19. 19. RESTFul APIを作る package main ! import ( "fmt" "github.com/drone/routes" "net/http" ) ! // GET用のHandler func getuser(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() id := params.Get(":id") fmt.Fprintf(w, "you are get user %s", id) } // PUT, DELETE, POST用の… ! func main() { mux := routes.New() // GET, PUT, DELETE, POST 用のハンドラー関数をroutingする mux.Get("/users/:id", getuser) mux.Put("/users/:id", modifyuser) mux.Del("/users/:id", deleteuser) mux.Post("/users/", adduser) http.Handle("/", mux) http.ListenAndServe(":9090", nil) } drone/routesとかgowebとかの ルーティング用の 3rd modulesを使う 大したことはやってないので、 net/httpだけで頑張る事も可能だが、 :idから始まる文字のパースと methodによるrouting処理が面倒なら こういうモジュール使うのもあり。
  20. 20. これだけで簡単なREST APIは作れる
  21. 21. DBアクセス https://gist.github.com/yosuke-furukawa/8552841
  22. 22. DBアクセス package main ! import ( "database/sql" _ "github.com/go-sql-driver/mysql" "log" ) ! func main() {   // sql.Open 第一引数にdriverの種類、第二引数に接続アドレスを指定、ここではhello に接続することを宣言。 db, err := sql.Open("mysql", "root@tcp(127.0.0.1:3306)/hello") // errがあればそれを表示 if err != nil { log.Fatal(err) } // deferで関数の終わりにそれをclose defer db.Close() }
  23. 23. DBアクセス package main ! import ( "database/sql" _ "github.com/go-sql-driver/mysql" "log" ) ! func main() {   // sql.Open 第一引数にdriverの種類、第二引数に接続アドレスを指定、ここではhello に接続することを宣言。 db, err := sql.Open("mysql", "root@tcp(127.0.0.1:3306)/hello") // errがあればそれを表示 if err != nil { log.Fatal(err) } // deferで関数の終わりにそれをclose defer db.Close() } sql.OpenでDBアクセス開始
  24. 24. SELECT操作 var ( id int name string ) // db.PrepareでPreparedStatement実行 stmt, err := db.Prepare("select id, name from users where id = ?") if err != nil { log.Fatal(err) } // statementのClose忘れずに。 defer stmt.Close() // stmt.QueryでQueryを実行 rows, err := stmt.Query(1); for rows.Next() { err := rows.Scan(&id, &name) if err != nil { log.Fatal(err) } log.Println(id, name) } defer rows.Close();
  25. 25. SELECT操作 var ( id int name string ) // db.PrepareでPreparedStatement実行 stmt, err := db.Prepare("select id, name from users where id = ?") if err != nil { log.Fatal(err) } // statementのClose忘れずに。 defer stmt.Close() // stmt.QueryでQueryを実行 rows, err := stmt.Query(1); for rows.Next() { err := rows.Scan(&id, &name) if err != nil { log.Fatal(err) } log.Println(id, name) } defer rows.Close(); db.PrepareでSQL実行する stmt.QueryでQueryを実行 ここでは、id=1を実行
  26. 26. INSERTとかUPDATEとかDELETEとか ! stmt, err := db.Prepare("INSERT INTO users(id, name) VALUES(?, ?)") if err != nil { log.Fatal(err) } res, err := stmt.Exec(2, "haruyama") if err != nil { log.Fatal(err) }
  27. 27. INSERTとかUPDATEとかDELETEとか ! stmt, err := db.Prepare("INSERT INTO users(id, name) VALUES(?, ?)") if err != nil { log.Fatal(err) } res, err := stmt.Exec(2, "gopher") if err != nil { log.Fatal(err) } stmt.Execで更新系のQueryを発行する
  28. 28. ここまでで簡単なDBアクセスと永続化はできる
  29. 29. ORM
  30. 30. こんだけある… http://present.go-steel-programmers.org/talk-review-orms/gsp-go-orms.slide#1
  31. 31. あんまり試せてない… シンプルでquery builderっぽいgorpか gormが良さそうだけど、API的には どれも有意差はない
  32. 32. Web Application Frameworks https://gist.github.com/yosuke-furukawa/8816249
  33. 33. TL;DR net/http martini, beego revel, falcore goweb, drone/routes gorilla/negroni need simple REST Framework toolkit/compatible with net/http Sinatra/Express like Fullstack RoR like
  34. 34. martini ! • フルスタックフレームワーク • martiniがsinatraならこっちはRoR, Play Framework、ちなみに初期ページすごくPlayっぽい • 中にmail senderやwebsocketも組み込まれてる • ミドルウェアもフィルターという概念を使うことで使 える • コード変更を検知して自動リロード/テストフレーム ワークが中にある、など開発にも便利
  35. 35. Falcore • 我らがngmoco製、最近はメンテをfitstarさんに 譲っている様子 • フルスタックフレームワーク • HUPを送ったら自動でprocessをforkして子プロ セスがreadyになったら自分を殺す動きをする • これにより、hot restartが可能になっている
  36. 36. beego • revelほど高機能ではないが、一応フルスタックフレームワーク • ドキュメントが超親切 • beego/ORMをサポートし、MVCに
 特化している • 中国では採用実績あり? ! ! ! ! !
  37. 37. martini ! ! • 人気がある(github/star的な意味で) • すごくSinatra/Expressライク • 基本的な機能しかコアには存在せず、ミドル ウェアで機能拡張する • 豊富なミドルウェアが存在している。 • ただし、作者はあんまり推してない。
  38. 38. martini ! ! • Martiniの作者がHTTP serverをより簡易的に、イディ オム的に扱えるようにするために開発したライブラリ • 正確にはフレームワークではなく、ライブラリ群 • 今後Martiniの代わりにスタンダードになる可能性があ るかも。 ! !
  39. 39. martini ! ! • こちらも正確にはツールキット • router, secure session, websocket等、まぁWebアプリ作 るには使うよねっていうのが ってる。 • isucon っていうweb アプリ高速化チューニングコンテスト で使われてる。 • 他にも実はrevelの中で使われてたりと汎用性高い。 !
  40. 40. WAFまとめ net/http martini, beego revel, falcore goweb, drone/routes gorilla/negroni need simple REST Framework toolkit/compatible with net/http Sinatra/Express like Fullstack RoR like
  41. 41. まとめ • Webサーバの建て方とnet/httpの
 基礎的な話 • DBアクセスの方法 • Web Application Framework
 まとめ
  42. 42. 今後やりたい事
  43. 43. 今後やりたい事 Go + socket.io で死ぬ予定

×