SlideShare a Scribd company logo
1 of 43
Download to read offline
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.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)	
}	
}
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を指定して起動
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()	
}	
}
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
で行われ、互いに影響しない作りになっている
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(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)	
}
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処理が面倒なら
こういうモジュール使うのもあり。
これだけで簡単な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.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()	
}
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アクセス開始
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();
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を実行
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)	
}
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を発行する
ここまでで簡単な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/compatible with net/http
Sinatra/Express like
Fullstack RoR like
martini
!
• フルスタックフレームワーク
• martiniがsinatraならこっちはRoR, Play
Framework、ちなみに初期ページすごくPlayっぽい
• 中にmail senderやwebsocketも組み込まれてる
• ミドルウェアもフィルターという概念を使うことで使
える
• コード変更を検知して自動リロード/テストフレーム
ワークが中にある、など開発にも便利
Falcore
• 我らがngmoco製、最近はメンテをfitstarさんに
譲っている様子
• フルスタックフレームワーク
• HUPを送ったら自動でprocessをforkして子プロ
セスがreadyになったら自分を殺す動きをする
• これにより、hot restartが可能になっている
beego
• revelほど高機能ではないが、一応フルスタックフレームワーク
• ドキュメントが超親切
• beego/ORMをサポートし、MVCに

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

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

まとめ
今後やりたい事
今後やりたい事
Go + socket.io で死ぬ予定

More Related Content

What's hot

FINAL FANTASY Record Keeperを支えたGolang
FINAL FANTASY Record Keeperを支えたGolangFINAL FANTASY Record Keeperを支えたGolang
FINAL FANTASY Record Keeperを支えたGolangYoshiki Shibukawa
 
Go言語のスライスを理解しよう
Go言語のスライスを理解しようGo言語のスライスを理解しよう
Go言語のスライスを理解しようYasutaka Kawamoto
 
GAE/GoでWebアプリ開発入門
GAE/GoでWebアプリ開発入門GAE/GoでWebアプリ開発入門
GAE/GoでWebアプリ開発入門Takuya Ueda
 
Hubotを使ってbotをつくろう!
Hubotを使ってbotをつくろう!Hubotを使ってbotをつくろう!
Hubotを使ってbotをつくろう!Daisuke Kikuchi
 
hubotで快適BOT生活
hubotで快適BOT生活 hubotで快適BOT生活
hubotで快適BOT生活 Kazufumi Otani
 
Go言語でBot開発やってみた
Go言語でBot開発やってみたGo言語でBot開発やってみた
Go言語でBot開発やってみたAkihiko Horiuchi
 
Pelicanによる www.python.jpの構築
Pelicanによる www.python.jpの構築Pelicanによる www.python.jpの構築
Pelicanによる www.python.jpの構築Atsuo Ishimoto
 
実践Go ツールの作成から配布まで
実践Go ツールの作成から配布まで実践Go ツールの作成から配布まで
実践Go ツールの作成から配布までYusuke Miyake
 
Go MobileでAndroidアプリ開発
Go MobileでAndroidアプリ開発Go MobileでAndroidアプリ開発
Go MobileでAndroidアプリ開発Takuya Ueda
 
node-gypを使ったネイティブモジュールの作成
node-gypを使ったネイティブモジュールの作成node-gypを使ったネイティブモジュールの作成
node-gypを使ったネイティブモジュールの作成shigeki_ohtsu
 
Python × Herokuで作る 雑談slack bot
Python × Herokuで作る 雑談slack botPython × Herokuで作る 雑談slack bot
Python × Herokuで作る 雑談slack botdcubeio
 
hubot-slack v4移行時のハマりどころ #hubot_chatops
hubot-slack v4移行時のハマりどころ #hubot_chatopshubot-slack v4移行時のハマりどころ #hubot_chatops
hubot-slack v4移行時のハマりどころ #hubot_chatopsknjcode
 
条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化Takuya Ueda
 
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツールPyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツールAtsuo Ishimoto
 
Goで言語処理系(の途中まで)を作ろう
Goで言語処理系(の途中まで)を作ろうGoで言語処理系(の途中まで)を作ろう
Goで言語処理系(の途中まで)を作ろうEsehara Shigeo
 
配布用Dotcloudによるすぐ始めるtwitterwebアプリ開発#twtr hack
配布用Dotcloudによるすぐ始めるtwitterwebアプリ開発#twtr hack配布用Dotcloudによるすぐ始めるtwitterwebアプリ開発#twtr hack
配布用Dotcloudによるすぐ始めるtwitterwebアプリ開発#twtr hackyut148atgmaildotcom
 
メルカリ・ソウゾウでは どうGoを活用しているのか?
メルカリ・ソウゾウでは どうGoを活用しているのか?メルカリ・ソウゾウでは どうGoを活用しているのか?
メルカリ・ソウゾウでは どうGoを活用しているのか?Takuya Ueda
 
Hubotをはじめる
HubotをはじめるHubotをはじめる
Hubotをはじめるnasa9084
 

What's hot (20)

FINAL FANTASY Record Keeperを支えたGolang
FINAL FANTASY Record Keeperを支えたGolangFINAL FANTASY Record Keeperを支えたGolang
FINAL FANTASY Record Keeperを支えたGolang
 
GoでMinecraftっぽいの作る
GoでMinecraftっぽいの作るGoでMinecraftっぽいの作る
GoでMinecraftっぽいの作る
 
Go言語のスライスを理解しよう
Go言語のスライスを理解しようGo言語のスライスを理解しよう
Go言語のスライスを理解しよう
 
GAE/GoでWebアプリ開発入門
GAE/GoでWebアプリ開発入門GAE/GoでWebアプリ開発入門
GAE/GoでWebアプリ開発入門
 
Hubotを使ってbotをつくろう!
Hubotを使ってbotをつくろう!Hubotを使ってbotをつくろう!
Hubotを使ってbotをつくろう!
 
hubotで快適BOT生活
hubotで快適BOT生活 hubotで快適BOT生活
hubotで快適BOT生活
 
Go言語でBot開発やってみた
Go言語でBot開発やってみたGo言語でBot開発やってみた
Go言語でBot開発やってみた
 
Pelicanによる www.python.jpの構築
Pelicanによる www.python.jpの構築Pelicanによる www.python.jpの構築
Pelicanによる www.python.jpの構築
 
実践Go ツールの作成から配布まで
実践Go ツールの作成から配布まで実践Go ツールの作成から配布まで
実践Go ツールの作成から配布まで
 
Go入門
Go入門Go入門
Go入門
 
Go MobileでAndroidアプリ開発
Go MobileでAndroidアプリ開発Go MobileでAndroidアプリ開発
Go MobileでAndroidアプリ開発
 
node-gypを使ったネイティブモジュールの作成
node-gypを使ったネイティブモジュールの作成node-gypを使ったネイティブモジュールの作成
node-gypを使ったネイティブモジュールの作成
 
Python × Herokuで作る 雑談slack bot
Python × Herokuで作る 雑談slack botPython × Herokuで作る 雑談slack bot
Python × Herokuで作る 雑談slack bot
 
hubot-slack v4移行時のハマりどころ #hubot_chatops
hubot-slack v4移行時のハマりどころ #hubot_chatopshubot-slack v4移行時のハマりどころ #hubot_chatops
hubot-slack v4移行時のハマりどころ #hubot_chatops
 
条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化
 
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツールPyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
PyCon JP 2012 hands-on セッション/ FlaskによるWebアプリケーションの実装とプログラミングツール
 
Goで言語処理系(の途中まで)を作ろう
Goで言語処理系(の途中まで)を作ろうGoで言語処理系(の途中まで)を作ろう
Goで言語処理系(の途中まで)を作ろう
 
配布用Dotcloudによるすぐ始めるtwitterwebアプリ開発#twtr hack
配布用Dotcloudによるすぐ始めるtwitterwebアプリ開発#twtr hack配布用Dotcloudによるすぐ始めるtwitterwebアプリ開発#twtr hack
配布用Dotcloudによるすぐ始めるtwitterwebアプリ開発#twtr hack
 
メルカリ・ソウゾウでは どうGoを活用しているのか?
メルカリ・ソウゾウでは どうGoを活用しているのか?メルカリ・ソウゾウでは どうGoを活用しているのか?
メルカリ・ソウゾウでは どうGoを活用しているのか?
 
Hubotをはじめる
HubotをはじめるHubotをはじめる
Hubotをはじめる
 

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

Microsoft Graph API Library for Go
Microsoft Graph API Library for GoMicrosoft Graph API Library for Go
Microsoft Graph API Library for Goyaegashi
 
Google Apps Scirpt勉強会 #1
Google Apps Scirpt勉強会 #1Google Apps Scirpt勉強会 #1
Google Apps Scirpt勉強会 #1ikikko
 
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力ThinReports
 
Express Web Application Framework
Express Web Application FrameworkExpress Web Application Framework
Express Web Application FrameworkLearningTech
 
Firefox5+HTML5×5
Firefox5+HTML5×5Firefox5+HTML5×5
Firefox5+HTML5×5dynamis
 
13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejsTakayoshi Tanaka
 
Rails and twitter #twtr_hack
Rails and twitter #twtr_hackRails and twitter #twtr_hack
Rails and twitter #twtr_hacki7a
 
環境構築から始めるDjangoチュートリアル
環境構築から始めるDjangoチュートリアル環境構築から始めるDjangoチュートリアル
環境構築から始めるDjangoチュートリアルsakihohoribe
 
ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用Yatabe Terumasa
 
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみようWebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみようmganeko
 
長いの
長いの長いの
長いのemasaka
 
Titanium Mobile
Titanium MobileTitanium Mobile
Titanium MobileNaoya Ito
 
複数アプリケーションの プロセスとログを管理する ための新しいツールと手法
複数アプリケーションのプロセスとログを管理するための新しいツールと手法複数アプリケーションのプロセスとログを管理するための新しいツールと手法
複数アプリケーションの プロセスとログを管理する ための新しいツールと手法Masaki Yatsu
 
Building production server on docker
Building production server on dockerBuilding production server on docker
Building production server on dockerHiroshi Miura
 
Building production server on docker
Building production server on dockerBuilding production server on docker
Building production server on dockerHiroshi Miura
 
Sohu邮箱的python经验
Sohu邮箱的python经验Sohu邮箱的python经验
Sohu邮箱的python经验Ryan Poy
 
Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!Shinpei Ohtani
 

Similar to ヒカルのGo 資料 Webアプリケーションの作り方 (20)

Microsoft Graph API Library for Go
Microsoft Graph API Library for GoMicrosoft Graph API Library for Go
Microsoft Graph API Library for Go
 
後期02
後期02後期02
後期02
 
Google Apps Scirpt勉強会 #1
Google Apps Scirpt勉強会 #1Google Apps Scirpt勉強会 #1
Google Apps Scirpt勉強会 #1
 
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
 
Express Web Application Framework
Express Web Application FrameworkExpress Web Application Framework
Express Web Application Framework
 
Firefox5+HTML5×5
Firefox5+HTML5×5Firefox5+HTML5×5
Firefox5+HTML5×5
 
APIMeetup 20170329_ichimura
APIMeetup 20170329_ichimuraAPIMeetup 20170329_ichimura
APIMeetup 20170329_ichimura
 
13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs
 
Rails and twitter #twtr_hack
Rails and twitter #twtr_hackRails and twitter #twtr_hack
Rails and twitter #twtr_hack
 
Apache Module
Apache ModuleApache Module
Apache Module
 
環境構築から始めるDjangoチュートリアル
環境構築から始めるDjangoチュートリアル環境構築から始めるDjangoチュートリアル
環境構築から始めるDjangoチュートリアル
 
ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用
 
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみようWebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
 
長いの
長いの長いの
長いの
 
Titanium Mobile
Titanium MobileTitanium Mobile
Titanium Mobile
 
複数アプリケーションの プロセスとログを管理する ための新しいツールと手法
複数アプリケーションのプロセスとログを管理するための新しいツールと手法複数アプリケーションのプロセスとログを管理するための新しいツールと手法
複数アプリケーションの プロセスとログを管理する ための新しいツールと手法
 
Building production server on docker
Building production server on dockerBuilding production server on docker
Building production server on docker
 
Building production server on docker
Building production server on dockerBuilding production server on docker
Building production server on docker
 
Sohu邮箱的python经验
Sohu邮箱的python经验Sohu邮箱的python经验
Sohu邮箱的python经验
 
Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!
 

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