gocon2016 spring 自作webフレームワーク uconを作った話
TRANSCRIPT
![Page 1: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/1.jpg)
自作Webフレームワーク uconを作った話
わかめ まさひろ
![Page 2: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/2.jpg)
わかめ まさひろ @v vakame
TypeScript
Masahiro Wakame
DefinitelyTypedappengine/go
photo from golang.org/doc/gopher/
![Page 3: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/3.jpg)
GoogleAppEngine/Go
神 いわゆる GOD
![Page 4: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/4.jpg)
諸君、私はappengine/goが好きだ
• 2008年4月 始まる
• サーバレスアーキテクチャ
• 2011年5月 Go対応始まる
• 2015年7月 Go, GAになる
• 2016年4月 Go 1.6対応1.9.35→❌ 1.9.36を使おう!
![Page 5: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/5.jpg)
Eric Schmidt said.
https://www.youtube.com/watch?v=HgWHeT_OwHc&t=1461GCP Next 2016 Day 1 Keynote
![Page 6: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/6.jpg)
GAE用ライブラリ作ってます• testerator github.com/favclip/testrator
• UnitTest高速化
• qbg github.com/favclip/qbg
• Datastore用TypeSafeクエリビルダ
• smg github.com/favclip/smg
• Search API用TypeSafeラッパproductionで利用中!
![Page 7: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/7.jpg)
GoCon 2015 Summer
• appengine専用じゃないけど
• jwg github.com/favclip/jwg
• genbase github.com/favclip/genbase
• GoCon 2015で話をしました!
• SlideShare goo.gl/45lZDK
![Page 8: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/8.jpg)
gb
• gb
• getgb.io/
• gb keeps the peace of our project🌹
• gb gae
• github.com/PalmStoneGames/gb-gae
![Page 9: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/9.jpg)
Google API Discovery Service
誰か知ってる?
![Page 10: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/10.jpg)
APIs Explorer is 神
https://developers.google.com/apis-explorer/
![Page 11: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/11.jpg)
APIs Explorer
• 誰でも簡単に使える
• 実際のAPIが叩かれる
• 結果を共有しやすい
• コードからUIが生成されている
![Page 12: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/12.jpg)
Cloud Endpoints• appengine専用の仕組み
• cloud.google.com/endpoints/
• 自前APIでAPIs Explorer使える
• APIの構造がわかる!
• 実例がわかる!(DevTool)
• UIを省く極道管理画面も!
![Page 13: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/13.jpg)
周辺ツールも充実• クライアントライブラリの自動生成
• golangだとこの辺全部そう
• github.com/google/google-api-go-client
• TypeScript用型定義の生成
• www.npmjs.com/package/gapidts
![Page 14: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/14.jpg)
but…
![Page 15: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/15.jpg)
Googleの闇の領域
ユーザ GAE闇
path mapping
request format
Version切替後reqをなかった事にcustom domain不可
![Page 16: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/16.jpg)
go-endpoints• CloudEndpoints用framework
• github.com/GoogleCloudPlatform/go-endpoints
• Service & Method の組み合わせで定義
• w http.ResponseWriterが取れない
• CloudEndpoints的には不要なので…
![Page 17: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/17.jpg)
評価• 細かい事を気にしなければかなり良い
• カスタムドメイン不可がやはり辛い
• デバッグ不可能な闇の領域が辛い
• ちょいちょいそこが不安定な気が…
• 拡張性が低い
• 横断的な処理を入れにくい…
![Page 18: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/18.jpg)
僕達が必要なもの
![Page 19: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/19.jpg)
Alt Cloud Endpoints• APIs Explorer的なものが欲しい!
• サバクラの意思疎通が楽• デバッグが楽
• コード→仕様が良い
• 仕様→コード は努力が必要(努力やだ• クライアントコードの生成
• 変わったら壊れてほしい
![Page 20: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/20.jpg)
代替ツールの検討
![Page 22: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/22.jpg)
✨swagger✨• Swaggerが一番良さそう!
• 個人の見解です
• Open API Initiative発足
• Swagger仕様をbaseに
• 長いものには巻かれたい
• Qiitaに少し書きました goo.gl/BLS3uH
![Page 23: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/23.jpg)
既存GoなSwagger実装の話
最初からswagger対応の物を選ぶと楽そう
![Page 24: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/24.jpg)
既存Go実装の比較• go-swagger
• goswagger.io/• type safeじゃない
• yvasiyarov/swagger• github.com/yvasiyarov/swagger• comment baseでつらい
• type safeじゃない
![Page 25: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/25.jpg)
既存Go実装の比較• go-restful
• github.com/emicklei/go-restful/• type safeじゃない
• goa• goa.design/• type safeじゃない
• DSLがヤバイ
![Page 26: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/26.jpg)
既存Go実装の比較
• grpc-gateway• github.com/gengo/grpc-gateway• gRPCのJSONなreverse proxy
• いつのまにかswagger対応してた
• appengineだと❌
![Page 27: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/27.jpg)
既存Webフレームワーク
![Page 28: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/28.jpg)
重要なポイント• net/httpに近いほうがわかりやすい
• あまりに独自っぽいのはちょっと…
• go-endpointsからの移行
• しばらくCloudEndpointsと両立したい
• コード上の互換性があると嬉しい…
• swagger-uiが使える
![Page 29: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/29.jpg)
既存フレームワーク調べた• なるべくnet/httpに近い
• revel→❌• なるべくCloudEndpointsのまま
• net/http→❌• goji→❌
• Swagger対応!
• martini→❌
![Page 30: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/30.jpg)
結論
•自分でつくろう
趣味に走ったわけではないです
![Page 31: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/31.jpg)
自分で作る話
![Page 32: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/32.jpg)
前提• appengine縛りにはしない
• とはいえappengineで使えないと困る
• net/httpに近いAPI
• 柔軟性
• go-endpointsとの互換性
• swaggerはopt-in やっていく
![Page 34: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/34.jpg)
名付け親
某a2cさん
martiniとか
ginとかに 対抗して
![Page 35: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/35.jpg)
名付け親
某a2cさん
uconと 名付けよう!
In japan, ucon (= turmeric) is to be effective in hangover.
![Page 36: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/36.jpg)
決めた後
某a2cさん
💩 ←ゆるさない!!
![Page 37: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/37.jpg)
仕様紹介
![Page 38: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/38.jpg)
まずgo-endpointss := &fooService{}api, err := endpoints.RegisterService(s, "foo", "v1", "Foo API", true)if err != nil { panic(err.Error()) } info := api.MethodByName("Get").Info()info.HTTPMethod, info.Path, info.Desc = “GET", "/foo/{id}", “Fooを1件取得する"
…
type IntIDRequest struct { ID int64 `json:"id,string" ̀}
func (s *fooService) Get(r *http.Request, req *IntIDRequest) (*FooJSON, error) { … }
![Page 39: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/39.jpg)
まずgo-endpointss := &fooService{}api, err := endpoints.RegisterService(s, "foo", "v1", "Foo API", true)if err != nil { panic(err.Error()) } info := api.MethodByName("Get").Info()info.HTTPMethod, info.Path, info.Desc = “GET", "/foo/{id}", “Fooを1件取得する"
…
type IntIDRequest struct { ID int64 `json:"id,string" ̀}
func (s *fooService) Get(r *http.Request, req *IntIDRequest) (*FooJSON, error) { … } Handler
Response
Setup
![Page 40: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/40.jpg)
まずgo-endpointss := &fooService{}api, err := endpoints.RegisterService(s, "foo", "v1", "Foo API", true)if err != nil { panic(err.Error()) } info := api.MethodByName("Get").Info()info.HTTPMethod, info.Path, info.Desc = “GET", "/foo/{id}", “Fooを1件取得する"
…
type IntIDRequest struct { ID int64 `json:"id,string" ̀}
func (s *fooService) Get(r *http.Request, req *IntIDRequest) (*FooJSON, error) { … }
Request
Response
闇の領域でもろもろ変換されてる
![Page 41: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/41.jpg)
ucon Features• net/http との類似性
• Routing• Method, Path Matching
• Middleware• Bubble• Dependency Injection
• Plugin
![Page 42: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/42.jpg)
API likes net/http
ucon.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {})
![Page 43: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/43.jpg)
API likes net/http
ucon.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {})
![Page 44: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/44.jpg)
Routing
ucon.HandleFunc(“*", “/“, … ucon.HandleFunc(“OPTIONS", “/“, … ucon.HandleFunc(“GET", “/“, … ucon.HandleFunc(“POST", “/“, … ucon.HandleFunc(“GET", “/api/user“, … ucon.HandleFunc(“GET", “/api/user/me“, … ucon.HandleFunc(“GET", “/api/user/{id}“, …
![Page 45: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/45.jpg)
Routing rule• METHODが一致する
• * 指定も可 厳密一致優先• Request Pathが一致する
• 複数候補ある場合より長い節一致• Request GET /api/user/123
• 🌟 GET /api/user/{id}• ❌ GET /api/user
• 先登録優先
![Page 46: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/46.jpg)
Middleware
• 1 request毎の処理に介入
• JavaでいうServletFilter
• ASP.NET MVCでいうFilter
• Logging, DI, CORS用Header, error→JSON変換 etc, etc…
![Page 47: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/47.jpg)
Middleware
Middleware
Middleware
Middleware
Handler
ServeHTTP DI
Cache-ControlCookieappengine.Context
etc, etc…
CORS Header
Path, Query, Body → JSON
*http.Requesthttp.ResponseWriter
![Page 48: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/48.jpg)
Middlewaretype MiddlewareFunc func(b *Bubble) error
type Bubble struct { R *http.Request W http.ResponseWriter Context context.Context RequestHandler interface{} ArgumentTypes []reflect.Type Arguments []reflect.Value Returns []reflect.Value }
func (b *Bubble) Next() error { … }
func (b *Bubble) do() error { hv := reflect.ValueOf(b.handler())
… b.Returns = hv.Call(b.Arguments) return nil}
var httpReqType = reflect.TypeOf((*http.Request)(nil))var httpRespType = reflect.TypeOf((*http.ResponseWriter)(nil)).Elem()
func HTTPRWDI() MiddlewareFunc { return func(b *Bubble) error { for idx, argT := range b.ArgumentTypes { if argT == httpReqType { b.Arguments[idx] = reflect.ValueOf(b.R) continue } if argT == httpRespType { b.Arguments[idx] = reflect.ValueOf(b.W) continue } } return b.Next() } }
![Page 49: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/49.jpg)
built-in middleware
• HTTPRWDI
• *http.Request, http.ResponseWriterのDI
• NetContextDI
• net/contextのContextをDI
![Page 50: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/50.jpg)
built-in middleware
• RequestObjectMapper
• path parameter, query paramter, post bodyをObjectに変換しDI
• ResponseMapper
• HandlerがreturnしたObjectやerrorをJSONに変換
![Page 51: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/51.jpg)
Plugin• プロセス起動時1回だけ動作
• 全Handlerの走査
• Handler→Plugin間の値の伝達機構
• swaggerはplugin
• 全Handlerの情報から処理
• swagger.json出力用Handlerの追加
![Page 52: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/52.jpg)
Plugintype pluginContainer struct { base interface{}} type HandlersScannerPlugin interface { HandlersScannerProcess(m *ServeMux, rds []*RouteDefinition) error }
type RouteDefinition struct { Method string PathTemplate *PathTemplate HandlerContainer HandlerContainer }
func (m *ServeMux) Prepare() { for _, plugin := range m.plugins { used := false if sc := plugin.HandlersScanner(); sc != nil { err := sc.HandlersScannerProcess(m, m.router.handlers) if err != nil { panic(err) } used = true } if !used { panic(fmt.Sprintf("unused plugin: %#v", plugin)) } } }
![Page 53: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/53.jpg)
Plugintype pluginContainer struct { base interface{}} type HandlersScannerPlugin interface { HandlersScannerProcess(m *ServeMux, rds []*RouteDefinition) error }
type RouteDefinition struct { Method string PathTemplate *PathTemplate HandlerContainer HandlerContainer }
func (m *ServeMux) Prepare() { for _, plugin := range m.plugins { used := false if sc := plugin.HandlersScanner(); sc != nil { err := sc.HandlersScannerProcess(m, m.router.handlers) if err != nil { panic(err) } used = true } if !used { panic(fmt.Sprintf("unused plugin: %#v", plugin)) } } }
![Page 54: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/54.jpg)
swagger plugin usageswPlugin := swagger.NewPlugin(…) ucon.Plugin(swPlugin)
s := &fooService{}tag := swPlugin.AddTag(&swagger.Tag{Name: "Foo", Description: ""})var info *swagger.HandlerInfoinfo = swagger.NewHandlerInfo(s.List)ucon.Handle("GET", "/api/foo/{id}", info)info.Description, info.Tags = "Fooを1件取得する", []string{tag.Name} …
type IntIDRequest struct { ID int64 `json:"id,string" ̀}
func (s *fooService) Get(r *http.Request, req *IntIDRequest) (*FooJSON, error) { … }
![Page 55: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/55.jpg)
go-endpoints(再掲s := &fooService{}api, err := endpoints.RegisterService(s, "foo", "v1", "Foo API", true)if err != nil { panic(err.Error()) } info := api.MethodByName("Get").Info()info.HTTPMethod, info.Path, info.Desc = “GET", "/foo/{id}", “Fooを1件取得する"
…
type IntIDRequest struct { ID int64 `json:"id,string" ̀}
func (s *fooService) Get(r *http.Request, req *IntIDRequest) (*FooJSON, error) { … }
![Page 56: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/56.jpg)
コード規模の話
• 本体 1329行
• ls | grep .go | grep -v _test.go | xargs wc -l
• swaggerプラグイン 1138行• find ./swagger -type f | grep .go | grep -v sample | grep -v _test.go | xargs wc -l
![Page 57: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/57.jpg)
利用事例
![Page 58: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/58.jpg)
利用サイト
• favclip
• 技術書典 応募サイト
• 怖くてOSSにでけんかったすまんな…
• Topgate社内では今後使っていくはず…
![Page 59: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/59.jpg)
swagger関連ツール
• swagger-uiの話
• Go用クライアントライブラリの話
• TypeScript用型定義ファイル生成の話
![Page 60: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/60.jpg)
求む!
![Page 61: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/61.jpg)
求む!
• 利用してみてブログ書く
• 利用してみて質問する
• 利用してみて…
自分が使えるようになると 満足するタイプ
![Page 62: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/62.jpg)
We are hiring
![Page 63: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/63.jpg)
We are hiring 1
•開発:テレビ朝日
• jwg, genbase 他 必要に応じて製造
• http://www.favclip.com/
• appengine/go 開発者絶賛募集中!
![Page 64: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/64.jpg)
We are hiring 2
• Topgate社も絶賛募集中です
• appengineできる人
• HTML, CSS, JS得意な人
•その他
![Page 65: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/65.jpg)
雑談
![Page 66: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/66.jpg)
https://github.com/golang/proposal/blob/master/design/15292-generics.md
![Page 67: GoCon2016 spring 自作Webフレームワーク uconを作った話](https://reader034.vdocuments.pub/reader034/viewer/2022051318/58f01e781a28abfb3d8b460b/html5/thumbnails/67.jpg)
👍for Web app