Your SlideShare is downloading. ×
ヒカルのGo 資料 Webアプリケーションの作り方
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

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

8,712
views

Published on

Published in: Engineering

0 Comments
25 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
8,712
On Slideshare
0
From Embeds
0
Number of Embeds
22
Actions
Shares
0
Downloads
27
Comments
0
Likes
25
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. How to create a Web application for Golang @yosuke_furukawa
  • 2. @yosuke_furukawa Node.jsユーザーグループ代表 / DeNA所属
  • 3. Golang歴:2ヶ月くらい 作ったもの ! - socket.io-go-emitter - golang + angularjs で chat sample - qiita アドベントカレンダーをスクレイピングす るツール
  • 4. Webアプリの作り方
  • 5. Webアプリの作り方 net/httpでのwebサーバの建て方 DBアクセス/ORM Web Application Framework
  • 6. golangの勉強会を有志の数名 集めてDeNAでやってた
  • 7. golangの勉強会をDeNAで やってた
  • 8. 今回の話はそのまとめ
  • 9. Goでweb applicationを 作る時に知っておいた方が 良いこと
  • 10. net/httpでWebサーバをたててみる https://gist.github.com/yosuke-furukawa/8309096
  • 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. 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. 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. 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. GoでRESTFul APIを作る
  • 16. RESTFul APIおさらい 各URIがリソースを表す このリソースを操作するため4つの HTTPのメソッドを扱う
  • 17. RESTFul APIおさらい /users/:id ユーザーを表現するためのリソース GET, POST, PUT, DELETE HTTP methodを使って操作する
  • 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. 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. これだけで簡単なREST APIは作れる
  • 21. DBアクセス https://gist.github.com/yosuke-furukawa/8552841
  • 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. 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. 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. 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. 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. 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. ここまでで簡単なDBアクセスと永続化はできる
  • 29. ORM
  • 30. こんだけある… http://present.go-steel-programmers.org/talk-review-orms/gsp-go-orms.slide#1
  • 31. あんまり試せてない… シンプルでquery builderっぽいgorpか gormが良さそうだけど、API的には どれも有意差はない
  • 32. Web Application Frameworks https://gist.github.com/yosuke-furukawa/8816249
  • 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. martini ! • フルスタックフレームワーク • martiniがsinatraならこっちはRoR, Play Framework、ちなみに初期ページすごくPlayっぽい • 中にmail senderやwebsocketも組み込まれてる • ミドルウェアもフィルターという概念を使うことで使 える • コード変更を検知して自動リロード/テストフレーム ワークが中にある、など開発にも便利
  • 35. Falcore • 我らがngmoco製、最近はメンテをfitstarさんに 譲っている様子 • フルスタックフレームワーク • HUPを送ったら自動でprocessをforkして子プロ セスがreadyになったら自分を殺す動きをする • これにより、hot restartが可能になっている
  • 36. beego • revelほど高機能ではないが、一応フルスタックフレームワーク • ドキュメントが超親切 • beego/ORMをサポートし、MVCに
 特化している • 中国では採用実績あり? ! ! ! ! !
  • 37. martini ! ! • 人気がある(github/star的な意味で) • すごくSinatra/Expressライク • 基本的な機能しかコアには存在せず、ミドル ウェアで機能拡張する • 豊富なミドルウェアが存在している。 • ただし、作者はあんまり推してない。
  • 38. martini ! ! • Martiniの作者がHTTP serverをより簡易的に、イディ オム的に扱えるようにするために開発したライブラリ • 正確にはフレームワークではなく、ライブラリ群 • 今後Martiniの代わりにスタンダードになる可能性があ るかも。 ! !
  • 39. martini ! ! • こちらも正確にはツールキット • router, secure session, websocket等、まぁWebアプリ作 るには使うよねっていうのが ってる。 • isucon っていうweb アプリ高速化チューニングコンテスト で使われてる。 • 他にも実はrevelの中で使われてたりと汎用性高い。 !
  • 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. まとめ • Webサーバの建て方とnet/httpの
 基礎的な話 • DBアクセスの方法 • Web Application Framework
 まとめ
  • 42. 今後やりたい事
  • 43. 今後やりたい事 Go + socket.io で死ぬ予定