Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
GoでRouter自作実装寄りな話
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
bmf_san
June 23, 2021
Programming
280
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GoでRouter自作実装寄りな話
bmf_san
June 23, 2021
More Decks by bmf_san
See All by bmf_san
桃太郎で始めるRego入門‐今日から使えるRegoの基本編
bmf_san
0
110
完璧を求めない意思決定-アクセス制御基盤における制約との向き合い方
bmf_san
5
20k
AAPについて調べてみた
bmf_san
0
160
レーダーをつくる
bmf_san
0
100
契約テストとPactについて
bmf_san
0
140
5分でわかるSLO
bmf_san
2
190
権限について考える
bmf_san
2
200
自作HTTPルーターから新しいServeMuxへ
bmf_san
3
1.9k
古くなってしまったPHPフレームワークとPHPのバージョンアップ戦略
bmf_san
1
540
Other Decks in Programming
See All in Programming
Snowflake Openflow Connector利用の勘所 / 20261024developersio2026tokyo-snowflake-openflow
kasacchiful
PRO
0
270
Vue.jsで作る空間解析アプリとCapacitorプラグインのData Bridge
hal_spidernight
1
160
オーケストレーション記述言語 Katari
yukikurage
0
220
AmebaブログはKMPから卒業します
kmars0605
0
310
3回つくってわかった、 定期実行ジョブ基盤の本質情報
takai
4
3.6k
AIが生成したコードは読むべきか?抽象化設計とコードの品質保証 / abstraction-design-and-quality
minodriven
14
8.3k
AI時代のIaC入門 〜なぜインフラをコードで管理したいのか?〜 / Introduction to IaC in the AI Era
akihisaikeda
6
1.3k
Spec-driven Development with AI
simas
PRO
0
2.2k
AI Augmentation Techniques with Liberty
ivargrimstad
0
300
Spec-Driven Development - Why Vaadin Is the Perfect Fit
simas
PRO
0
210
Web3Dライブラリを作ってVue Custom Rendererの仕組みを理解しよう / lets learn vue custom renderer by making 3d library
drumath2237
1
120
AI時代のシニアエンジニアとは
yosuke_furukawa
PRO
14
11k
Featured
See All Featured
Testing 201, or: Great Expectations
jmmastey
46
8.4k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
490
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
560
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Docker and Python
trallard
47
4.2k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Bootstrapping a Software Product
garrettdimon
PRO
306
120k
How GitHub (no longer) Works
holman
316
150k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
550
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
1k
From π to Pie charts
rasagy
1
430
Transcript
GoでRouter⾃作 実装寄りな話 @bmf_san 2021.06.23 社内LT
なんの話 • net/httpを拡張したrouterのライブラリ • net/httpの”⾜りないところ”を補う • /user/:idのような動的なルーティングができな い
ϒϩάͱ͔-5ͱ͔Ͱ͍·Θͨ͠ωλ
Github https://github.com/bmf-san/goblin
Goblin仕様 • net/http準拠 • 動的なルーティング • 名前付きのパラメータ(パスパラーメーター)をサポート/ users/:id • 正規表現も使える
/users/:id[^\d+$] • ミドルウェアをサポート • net/httpのhttp.Handlerインターフェースに従った関数をミドル ウェアとしてルーティングの処理に組み込める
Goblin例 IUUQTHJUIVCDPNCNGTBOHPCMJOCMPCNBTUFS@FYBNQMFTNBJOHPΛࢀর
有名どころ • ライブラリ • https://github.com/fasthttp/router • https://github.com/julienschmidt/httprouter • http://github.com/go-chi/chi •
FW • https://github.com/gin-gonic/gin • https://github.com/labstack/echo • https://github.com/gorilla/mux
Routerの役⽬ NJEEMFXBSFIBOEMFSͷखલͰॲཧ͞ΕΔΠϝʔδ
Routerの役⽬ • リクエストされたURLやHTTP Methodに応じて、 処理の実⾏を制御するアプリケーション • URLとアプリケーションの処理を結びつける
データ構造を考える ・Router≒⽂字列マッチング ・URLの階層構造と相性が良いデータ構造 →⽊構造
⽊構造
トライ⽊(プレフィックス⽊) ・⽂字列の集合を扱う⽊構造の⼀種 ・ざっくりいうと、⽂字列を探索しやすいように⽊に 格納したやつ ・ex. サジェスト、IPアドレス探索、形態素解析とか ⽂字列を扱う系のやつのベースだったりするぽい
もっと良い⽊ • 時間的計算量(処理時間)、空間的計算量(メモ リ)の効率を追求するなら他に選択肢がある • ex. Radix(Prefix) tree https://www.cs.usfca.edu/ ~galles/visualization/RadixTree.html
• 実装できなかった。ムズい。 • strings.Replacerは内部でRadix tree 実装してい る
トライ⽊を知る • https://www.cs.usfca.edu/~galles/visualization/ Trie.html • アルゴリズムのビジュアライズ • https://github.com/bmf-san/road-to-algorithm- master/tree/master/data_structures/tree/trie •
参照実装
オレオレトライ⽊
オレオレトライ⽊(旧) • 最初のリリースで実装していた⽊ • HTTPメソッドをノードに⼊れてしまうのはアンチパターンだった • ルーティングの処理にHTTPメソッドの⼀致を前提としてしまう • HandlerがHTTPメソッドに依存するような実装になってしまう •
middlewareの対応で不都合に • cf. https://bmf-tech.com/posts/⾃作ルーティングをアップデートした
主な構造体 NBQͱMJOLFEMJTUͷ߹ମͰΛදݱͨ͠Α͏ͳΠϝʔδʁ
Goでrouterを実装する上で知っておきたいこと • net/httpの概観 • どんな構造体があるか、どこを拡張したら良いか、どんなイン ターフェースに従うべきか • cf. https://golang.org/pkg/net/http/ •
HTTPサーバーの処理 • http.ListenAndServeから内部を⾒る • cf. https://bmf-tech.com/posts/GolangのHTTPサーバーのコード リーディング
HTTPサーバーのコードにdeep dive • 良く⾒るGoのHTTPサーバーのコード(⾊々省略さ れている)
HTTPサーバーのコードにdeep dive • 省略しないで書いたパターン
HTTPサーバーのコードにdeep dive • ServeHTTPは関数型のaliasであるHandlerFuncに置き換えることができる • cf. • func (f HandlerfFunc)
ServeHTTP(w ResponseWriter, r *Request) • https://golang.org/src/net/http/server.go?s=64180:64240#L2058
HTTPサーバーのコードにdeep dive • Mux(http.NewServeMux( ))は作らなくても良い。DefaultServeMuxを使うことができ る。 • DefaultServeMuxはServeMux型の構造体を持っており、HandlerFuncというmuxにルー ティングを登録する関数を実装している。 •
cf. • DefaultServeMux • https://golang.org/src/net/http/server.go?s=77627:77714#L2269 • func (mux *ServeMux) HandlerFunc(pattern string, handler func(ResponseWriter, *Request))
HTTPサーバーのコードにdeep dive • Server構造体(http.Server{})もわざわざ作らなくても良い。net/httpには ListenAndServe( )が⽤意されている。 • cf. • func
(*Server) ListenAndServe • https://golang.org/pkg/net/http/#ListenAndServe • func ListenAndServe(addr string, handler Handler) error
Routerを実装するには • →http.Handlerインターフェース を意識して、muxを作れば良い
ルーティングを登録する部分の実装 • cf. https://github.com/bmf-san/goblin/blob/master/router.go • メソッドチェーンでrouteを登録する処理 • ServeHTTPの実装(≒http.Handlerインターフェースの実装)した構造体を作る • ServeHTTP内では、ルーティング、ミドルウェア・ハンドラの実⾏を順番にやる
• 作った構造体はListenAndServeに渡される想定 • cf. https://github.com/bmf-san/goblin/blob/master/_examples/main.go
middleware対応のための実装 • cf. https://github.com/bmf-san/goblin/blob/master/ middleware.go • Sliceに保持したミドルウェアを順番に処理していく • 処理をラップしていくように実⾏する •
cf. https://github.com/bmf-san/goblin/blob/ master/_examples/main.go • いわゆるDecorator patternってやつだと思う
muxにあたる部分の実装 • cf. https://github.com/bmf-san/goblin/blob/master/trie.go • オレオレトライ⽊を頑張ってかく • 単純なトライ⽊を書いて、それを発展させていく • データ構造を考えきった時点で6~7割くらい完成ではある
• テストとデバッガを有効につかう • テストがないと前に進めないくらいテストを有⽤ • ⾊々なパターンのルート定義を考慮する必要があり、テストケースが結構悩ましい • デバッガは⽊の⽣成が上⼿くできているか確認したり、脳内デバッグで間に合わないときに有⽤ • 正規表現の利⽤ • 正規表現を使ったルーティングのケースに対応するためにregexpを使っている • strings.Replacerで代⽤できるならそっちが良い • Goでは正規表現はコストがかかる処理なのでキャッシュして再利⽤性を⾼めると良い • 後で対応しようと思っていたらPRもらえた • https://github.com/bmf-san/goblin/pull/17
ベンチマーク • ϕϯνϚʔΫςετ • cf. https://github.com/julienschmidt/go-http-routing-benchmark • go test -bench=“Goblin|Gin|GorillaMux|HttpRouter|Chi|Beego|Echo”
• ϕϯνϚʔΫ݁Ռ • cf. https://github.com/bmf-san/goblin/issues/ 34#issuecomment-864978325 • Routerબఆͷ؍ύϑΥʔϚϯε͚ͩͰͳ͘ɺػೳ໘net/ httpͷΠϯλʔϑΣʔεΛҙ͍ࣝͯ͠Δ͔Ͳ͏͔ͷόϥϯε͕େࣄ ͦ͏ • cf. https://github.com/julienschmidt/go-http-routing- benchmark#conclusions
ベンチマーク • cf. https://github.com/julienschmidt/go-http-routing- benchmark • GoblinՃ͠·ͨ͠ରઓΑΖ͓͘͠Ͷ͕͍͠·͢PR • https://github.com/julienschmidt/go-http-routing- benchmark/pull/97
• READMEߋ৽͍ͯ͠ͳ͍͔ΒϦετݟͨͧ͠PR • https://github.com/julienschmidt/go-http-routing- benchmark/pull/96