Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
gopls拡張によるマイクロサービス間の 実装ジャンプの改善
Search
Shotaro Yamasaki
September 28, 2025
380
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
gopls拡張によるマイクロサービス間の 実装ジャンプの改善
GoConference2025
Shotaro Yamasaki
September 28, 2025
More Decks by Shotaro Yamasaki
See All by Shotaro Yamasaki
noCopyとその展望
yadon3141
0
700
Featured
See All Featured
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
210
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
Optimising Largest Contentful Paint
csswizardry
37
3.8k
KATA
mclloyd
PRO
35
15k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
310
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Context Engineering - Making Every Token Count
addyosmani
9
1k
How STYLIGHT went responsive
nonsquared
100
6.2k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
Transcript
gopls拡張による マイクロサービス間の 実装ジャンプの改善 株式会社サイバーエージェント 山﨑正大朗 Github @seipan Go Conference 2025
1.WINTICKET での課題 2.LSPについて 3.goplsについて 4.gopls拡張 5.拡張goplsの運用 6.感想
山﨑 正大朗/yadon 株式会社サイバーエージェント 株式会社WINTICKET 2025新卒入社 初登壇で緊張しています @seipan
はじめに
みなさんこんなことありませんか
ん〜 定義ジャンプで 実装にジャンプしたい のにinterfaceに飛ぶ
今回はそれを解決する話です
WINTICKETでの課題
WINTICKETについて 01
None
WINTICKETでの開発体制 WINTICKETは複数のマイクロサービスで構成されている Rsource Cloud Spanner Cloud BigQuery Cloud Storage Gateway-XXX
Pods Web Cloud Run Microservices Pods Logging Profiler Management Tools Cloud Pub/Sub User iOS Android Web Firebase Fastly CDN Cloud DNS Cloud Load Balancing d Live Elemental MediaPackage Elemental MediaLive CloudFront CloudWatch Event Secret Manager API Gateway Lambda ChateauAmeba Cloud Armor
・各マイクロサービス間の通信は gRPCで行われている。 ・全てのマイクロサービスのソースコードは単一の Github リポジ トリ で管理されている (モノレポ)。 ・各マイクロサービスは依存しあっている。 ・機能開発では複数のマイクロサービスを跨いだ開発をすることが あ る。
WINTICKETでの開発体制
・各マイクロサービス間の通信は gRPCで行われている。 ・全てのマイクロサービスのソースコードは単一の Github リポジ トリ で管理されている (モノレポ)。 ・各マイクロサービスは依存しあっている。 ・機能開発では複数のマイクロサービスを跨いだ開発をすることが あ る。
WINTICKETでの開発体制
WINTICKETでの開発 マイクロサービス A マイクロサービス B gRPC
WINTICKETでの開発 マイクロサービス A マイクロサービス B gRPC これらに変更を加えたい場合
WINTICKETでの開発 マイクロサービス A マイクロサービス B gRPC
WINTICKETでの開発 マイクロサービス A マイクロサービス B gRPC 定義ジャンプ!
WINTICKETでの開発 マイクロサービス A マイクロサービス B gRPC 定義ジャンプ!
WINTICKETでの開発 マイクロサービス A マイクロサービス B gRPC proto 生成 定義ジャンプ! **.pb.go
GoLandとか VSCodeでも Go to Implementations とかなら、、、、
GoLandとか VSCodeでも Go to Implementations とかなら、、、、
実装を探したい 関数名コピーして 実装のディレクトリに移動して grepして 実装探して、、、、
実装を探したい 関数名コピーして 実装のディレクトリに移動して grepして 実装探して、、、、
gopls VSCode拡張 解決したい
LSPとは
LanguageServerとは コード補完、定義ジャンプ、リファレンス検索、リントなどの機能 をIDEに提供するもの。 ・Rust: rust-analyzer ・Scala: metals ・Typescript: typescript-language-server など
goplsとは オープンソースの Go言語のLanguage Server
LSPとは LSP(Language Server Protocol)とは JSON-RPCベースのプロトコ ルで、IDEとLanguageServer間の通信の標準仕様 https://code.visualstudio.com/api/language-ext ensions/language-server-extension-guide
例 ・textDocument/definition カーソル位置のシンボルが定義されている場所を問い合わせる。 ・textDocument/completion カーソル位置で利用可能な補完候補を問い合わせる。 ・textDocument/implementation インターフェースや抽象メソッドなどの実装先を問い合わせる
goplsについて
定義ジャンプの大まかな流れ gopls 定義ジャンプしたい ジャンプ textDocument/definition 位置を返す LSP
goplsの実装を追ってみる JSON-RPCのメソッドで 処理を分岐させる ファイル種別で処理を 分岐させる
golang.Definitionを追ってみる① 以下のパターンだと別の処理 ・import文 ・package名 ・embed directive ・Linkname directive ・DocLink
golang.Definitionを追ってみる② 以下のパターンでも別の処理で ・return ・continue ・break ・goto
golang.Definitionを追ってみる③ その後通常の識別子として判別 ・referencedObject カーソル位置の types.Objectを取得 ASTを取得してき、 info.ObjectOfで 定義元のObjectを取得
golang.Definitionを追ってみる④ ・ObjectLocation ③のtypes.Objectの位置を取 得 start = obj.Pos() end = start
+ token.Pos(namelen) でLocationを組み立てている
問題の定義ジャンプ改善 通常の識別子上での位置を返す前に RPCの実装を見にけば解決できそう、、、、!
ここでクイズ ~定義ジャンプ何処に飛ぶでしょう ~ return break
ここでクイズ ~定義ジャンプ何処に飛ぶでしょう ~ return break
ここでクイズ ~定義ジャンプ何処に飛ぶでしょう ~ ASTを上に辿って、 関数が見つかったら停止 関数の戻り値の位置を返 している
ここでクイズ ~定義ジャンプ何処に飛ぶでしょう ~ for, range文の場合 breakなら 最後(“}“) continueなら 最初(“for”) の位置を返す
gopls拡張
goplsを拡張する 追加する
1. 定義元がproto配下であるか確認 v.microserviceA.GetUser ↑だと microserviceAが proto配下であるか importPath を見て確認する。
1. 定義元がproto配下であるか確認 ASTを取得 識別子の検証 importPath を確認
2. 定義元のマイクロサービス名を取得 microserviceA.GetUserやclient.GetUser microserviceA, clientのpathを確認。 WINTICKETでは/proto/{{マイクロサービス名 }}のように なっているので、 1と同じように、 imortPathからマイクロ
サービス名を取得してくる。
3. 2で取得したパッケージで RPCの実装を探索 WINTICKETでは/pkg/{{マイクロサービス名 }}となっている ので、マイクロサービスのディレクトリで探索を行う。
4. 位置を返す ファイルを 1行ずつ分割し、 正規表現で頑張る。 マッチしたら FindStringIndex , strings.Indexで正確な位置を 取得し、protocol.Locationを
組み立て返却する。
gopls拡張で思ったこと 愚直に頑張るしかない ・汎用的なものを作るのは難しい ・ディレクトリ構成は中々変わらない ・それよりも正確に飛ぶことを頑張る
拡張goplsの運用
拡張したgoplsをどう使っていくか
拡張goplsのコード管理 1. github.com/golang/tools をprivateリポジトリに forkする ・ドメイン固有のロジックが入っているため 2. submoduleでWINTICKETのソースコード配下に置く ・ソースコード配下で拡張 goplsをビルドするため
拡張したgoplsをどう使っていくか 1. デフォルトの goplsを拡張した goplsに置 き換える 2. RPCの実装に飛ぶ専用の定義ジャンプ を作って、そこでだけ拡張 goplsを使う
拡張したgoplsをどう使っていくか 1. goplsを拡張した goplsに置き換える 2. RPCの実装に飛ぶ専用の定義ジャンプ を作って、そこでだけ拡張 goplsを使う
理由 他のlanguageServerの機能も拡張 goplsに乗っかる ことになる →メンテナンスが大変。 textDocument/definitionが完全に置き換わってしま う。 →逆にinterfaceに飛びたい時に不便
普段 gopls 定義ジャンプしたい ジャンプ textDocument/definition 位置を返す LSP
新しい定義ジャンプ 拡張gopls gRPCの実装に 定義ジャンプしたい ジャンプ textDocument/definition 位置を返す LSP VSCode拡張
新しい定義ジャンプ 拡張gopls gRPCの実装に 定義ジャンプしたい ジャンプ textDocument/definition 位置を返す LSP VSCode拡張
新しい定義ジャンプ 拡張gopls gRPCの実装に 定義ジャンプしたい ジャンプ textDocument/definition 位置を返す LSP VSCode拡張 普段
gopls 定義ジャンプしたい ジャンプ textDocument/definition 位置を返す LSP 共存させる
gopls 拡張gopls 従来の操作 RPC の実装に飛びたい
VSCode拡張 Go to gRPC Definitionを追加
VSCode拡張 1. 呼び出されたら拡張 goplsを起動する 2. textDocument/definitionリクエスト 3. レスポンスを受け取ったらその位置に ジャンプする
飛べた!!!!
感想
1. 簡単に拡張はできる 2. 大切なのはジャンプの正確性と速さ
ありがとうございました