Yappli Tech Blog

株式会社ヤプリの開発メンバーによるブログです。最新の技術情報からチーム・働き方に関するテーマまで、日々の熱い想いを持って発信していきます。

Go Conference 2021 Autumnで個人的に気になった発表まとめ

サーバーサイドエンジニアの森谷です。

11/13 にGo Conference 2021 Autumnが開催されました。
ヤプリもSiliverスポンサーとして参加していたのですが、みなさんもうご覧になりましたか?
今回は個人的に気になったセッションをまとめてみたので、もしまだ視聴が追いついていない方がいましたら参考になれば幸いです。

今回取り上げるセッションですが、自分のGoのレベルであったり自分にとっての実用性であったりといった点から大きく偏りがあることをご了承ください。
紹介する以外にも面白い発表は多数ありましたので、余力がありましたら全て視聴することをおすすめします(脳筋)。

各セッションにはGoCon公式サイトのリンクを載せており、リンク先にYoutubeのアーカイブとスライドが載っています。

Learning Computer Systems by Crafting: Shell (作って学ぶシェル)[20min]

gocon.jp

Bashなどのシェルの知識をどこで学ぶか、ネット上でたまに議論になるネタです。空気のような存在であるからこそ存在に気づきにくいシェルを、Goを使ってPOSIXシェルのサブセットを作りながら、シェルの役割や機能について学びます。

Goの界隈ではお馴染みの、フューチャー株式会社の渋川さんによるセッションです。
シェルとは何か?の説明から始まり、Goから外部コマンドを叩く処理の解説、シェルの作り方の解説、デモといった流れでした。

まずシェルについての説明がわかりやすく、広義のシェル・狭義のシェル・さらに狭義のシェルといった分類で図解されています。
また自作の過程を追いながら、シェルの仕事についてステップ毎に整理立てられた説明をされています。
自分は今までこの辺はなあなあでしか理解していなかったのですが、知識の整理に大変参考になりました。

ちなみに、セッションの最後で紹介がありましたがフューチャーさんのテックブログは600記事ほどあるとのこと!
Go関連の調べごとをするたびに高確率でヒットするので「ここなんでもあるなあ」と思っていましたが、納得しました。

Go Contextを完全に理解する [40min]

gocon.jp

Goではcontext.Contextを利用することで、キャンセルやタイムアウトを効率よく安全に実装することができます。 ContextはDBクライアントなど各種ライブラリを使う際に、対応する関数の引数にするだけでも動作します。 Contextはとても抽象度の高い存在ですが、実体はわずか数百行のコードで完結したライブラリです。 それだけの行数で動作するよう、非同期処理、インターフェースが高度に実装されています。 詳細な実装まで読み解いて、Contextをしっかりと理解してみたくなりませんか。

フューチャー株式会社のMasahiko Itoさんによるセッションです。
スピーカーの方も触れていましたが、contextについては後のセッションでも登場するさき(H.Saki)さんによるZennの書籍が凄まじく、contextの歴史や意義、使い方などを学ぶには最適な書籍が発表されています。
(自分の中で、Go初心者の頃に読みたかった本Top3に入ります。これが無料ってダメでしょと思えるクオリティです。)
本セッションでは上記の目的は書籍に譲られており、contextの内部実装、具体的にはcontextパッケージのコードリーディングに専念しています。

contextパッケージは思いのほかコンパクトで全体で570行ほどしかなく、よって全てを40分で解説しています。
このパッケージは並行処理のお手本となるようなコードが山のようにあり、またその一つ一つを丁寧に解説されているため、並行処理の知見を深めたい方にはとてもオススメのセッションだと感じました。
playgroundを用いた簡略化した例を逐一提示してくださっていたのもわかりやすかったです。
弊社は隔週ペースで標準パッケージのコードリーディングをする会を開いているのですが、contextパッケージを読む際には事前にこの発表を聞いておくと理解度がバツグンに上がりそうだなと思いました。

セッションの最後に「Goはシンプルでアレが足りない、とかよく言われるけど言うほどGoを使いこなしてる?」という問いかけをされていましたが、深く同意する発表でした。

io/fs.FS for testability. io/fs.FS for abstraction. [20min]

gocon.jp

Go 1.16から追加されたio/fsパッケージが提供しているインターフェースについて、皆さんはどのような目的で活用していますか? 私は、主に2つの目的で活用しています。1つはテスト容易性(テスタビリティ)、もう1つはファイルシステムとしての抽象化です。 本発表では、具体的な事例を元に上記の2つの目的での使い方を紹介します。 また、fs.FSインターフェースを使ったことで失敗した事例も紹介したいと思います。 本発表を通じてio/fsのインターフェースの利用イメージを持ってもらえれば嬉しいです。

GMOペパボ株式会社のKen'ichiro Oyamaさんによるセッションです。
fstestパッケージをベースにファイルが絡むテストの書き方を紹介し、またFSインターフェースの幅の広さを解説しています。

自分はまだまだfstestを使いこなせていないのですが、 fstest.MapFS などとても便利な関数がいくつもあるなと知りました。
後半はLinuxのファイルシステムの抽象化の思想と絡めてGoのFSインターフェースの説明をしており、両者の理解を後押ししてくれます。
また自作gitコマンドを用いた説明が面白く、「GitHubのリポジトリをファイルシステムとして抽象化することで、GitHub APIをどう叩いてファイルを検索するかという関心の分離ができた」というパートは、なるほどこう使うのかと勉強になりました。

後のセッションでtenntennさんもFSに絡んだ発表をされているのですが、そちらはFSの基礎の話にも軽く触れていましたので、先にtenntennさんのセッションを見てからこちらを視聴するとより理解が深まるかもしれません。

二相コミットなどの具体例に見るゴルーチンとチャネルの使いどころ [20min]

gocon.jp

実務で実際に遭遇したゴルーチンとチャネルの使用事例を通して、その一般的な使いどころを考えます。 CloudSQLとDatastore双方のデータの更新のためにGo言語で二相コミットの実装をした事例や、待ち時間がかかる処理をゴルーチンに逃がしAPI呼び出しのレイテンシを改善した事例を紹介します。

株式会社Mobility TechnologiesのKoji Aomatsuさんによるセッションです。
実務で使っているコードをベースにゴルーチンの解説をされています。

ゴルーチンを、「待つゴルーチン(同期を取りながら実行されるもの)」と「逃すゴルーチン(同期の必要がないもの)」と分類して話を進めていたのがわかりやすかったです。
二相コミットの実装部分も面白かったのですが、個人的にはゴルーチンやチャネルを使う際の注意が随所で解説されるのがとても勉強になりました。
「チャネルを使う際はコメントだいじに」「裏側で動いている処理は動作が見えにくいからログだいじに」といった教訓はなるほどと思いました。
(とはいえ怖いので極力チャネルは使いたくないですね。。。)

Golangで作るSQL Language Server(sqls) [20min]

gocon.jp

私はGo言語でsqlsというSQL Language Serverを作りました。sqlsはSQLを静的解析し、DBから取得されたテーブルやカラム情報を組み合わせて、自動補完やドキュメント表示など、開発に必要なインテリセンスを提供するサーバーです。 利用するクライアントとの通信にLanguage Server Protocol(LSP)を用いることであらゆるエディタが、sqlsの支援を受けることができます。

株式会社Mobility Technologiesのlighttiger2505さんによるセッションです。
エディタでSQLがゴリゴリ補完されていました。すごい。
テーブル名も補完されていました。すごい。
テーブル名にマウスをホバーすると定義が表示されていました。すごい。使いたい。

セッションの中身はLanguage Serverの自作という未知なものにどう向き合っていったか、といった面が色濃く現れた内容でした。
どう最小要件をまとめて歩き出すかといった整理の例や、「○○がやりたい → 既存の似たようなやつを参考に、なんかパッケージとかあるだろう → あった」というようなアタリの付け方が素晴らしく、学ぶべきだなと感じました。
パッケージやツールの理解に対しても、「○○を理解したい → なんかよくわからん → とりあえず使ってみた → こういうデバッグをすればわかるでしょう」というプロセスを実例とともに披露されていました。
開発の進め方という観点で非常に勉強になるセッションでした。

io/fsパッケージを用いたテスタブルなコード生成ツールの開発 [40min]

gocon.jp

io/fsパッケージによりOSのファイルシステムに依存しない処理を書けます。例えば、複数のファイルを生成するツールの開発において、生成したファイル群をtxtar形式で出力し、ファイルシステムとして扱うことでテストを容易にできます。また、複数のファイルにまたがるテンプレートをtxtar形式として扱い、それをファイルシステムとして解釈することでtext/templateパッケージでパースでき、保守しやすさと可読性を両立できます。本セッションでは、skeletonという静的解析ツールのコードの雛形を生成するツールの開発で用いているio/fsパッケージを使ったいくつかの手法についてご紹介します。

tenntennさんによるセッションです。
skeletonというGoの静的解析コードの雛形を自動生成するツールの紹介と、その中でファイルを扱ったテストにfs.FSを活用した話です。

前半はfs.FSインターフェースやembedパッケージの説明を行なっています。
基礎的な解説から始まり、「ZIPファイルをFSで扱い、中のテンプレートファイルを展開せずに使う」といった実例とともに説明しています。
安定のわかりやすい資料・解説ですので、この辺りがまだ曖昧だという方は前半だけでも試聴するのをオススメします。
後半は複数のファイルの取り扱いに便利なtxtar形式の紹介とゴールデンファイルテストの話をされています。
自分はゴールデンファイルテストについては初耳だったのですが、期待値をファイルで用意し、それと差分をとることで確認するテスト手法とのことです。
これとtxtar形式との組み合わせの相性が良く、コード生成をする際には強力に活用できそうだなと感じました。

最後にリアルタイムでコーディングを行うデモの時間があるのですが、ほとんど補完に頼らずに己の力でコードを書いていく様には改めて笑みが溢れました。
import文まで自分の手で書いており、goimportsに甘えている自分はまだまだだなと痛感しました(迷走)。

ところでCMですが、tenntennさんには弊社の技術顧問に就任いただいており、隔週の社内勉強会でご教授をいただいています!

スケジューラから学ぶGoランタイム 〜 code reading of runtime pkg〜 [40min]

gocon.jp

Goにおいて複数のゴールーチンを並行に実行するためのスケジューラは、Goランタイム内で実装されています。しかし現在のスケジューラの大枠が実装されたのは9年前のGo1.1であり、世の中におけるGoのスケジューラ解説はそのときに世に出た公式設計書を元に、視覚的な図ベースで組み立てられているものがほとんどです。本セッションでは、スケジューラの挙動について実際のruntimeパッケージ内のコードベースで理解することを目的に、スケジューラについての説明体系を再構築します。

先ほども触れました、さき(H.Saki)さんのセッションです。
個人的には、今回のカンファレンスの中で最も難しいテーマで、かつ最もわかりやすいセッションだったと感じています。とにかく凄まじいプレゼンでした。

ランタイムとは何かという説明から始まり、Goランタイムのコンポーネントについて、それらをどうコントロールしてゴルーチンを制御しているのかといった内容です。
思い出す限りほとんどのページに図解が載っており、体系だった説明の流れも非常にスムーズでした。
歴史や背景の調査も徹底されており、「既存のよくある説明はこれがわかりにくい」という指摘とそれを踏まえた解説は見事でした。
ランタイムに興味のない方であっても、プレゼンを学ぶ目的での試聴をオススメしたいセッションでした。

ランタイムパッケージのコードリーディングは闇のゲームが始まりそうで忌避していたのですが、少しだけ読んでみてもいいかも...と思えるようになったかもしれません。

Floating Point Numbers and Decimal in Go [20min]

gocon.jp

プログラミングにおける小数の扱いは、注意が必要な定番のポイントだと思います。特に、精緻な計算が必要な処理では、桁落ちやオーバーフローを考慮することになります。 Goでは、組み込みの型の小数の挙動に少し独特な部分があります。また、精緻な計算を要求される場面では、math/bigパッケージなど、細かい小数を扱う仕組みも標準で提供されています。 そこでこのセッションでは、Goの組み込みの文法での小数の挙動を実際に見た上で、汎用的なアプローチとして、公式のmath/bigやサードパーティーのshopspring/decimalパッケージを利用した小数の取り扱い方法を紹介したいと思います。

株式会社UPSIDERのRyoya Sekinoさんによるセッションです。
一般的な小数を扱う際の注意、Goならではの挙動、小数計算を行う際のユースケースごとのススメをまとめていました。

こちらもまたわかりやすい説明と綺麗にまとまった資料で、弊社の新人メンバーにオススメしたいセッションでした。
型なしの定数で小数を扱うと挙動が変わるよといった、型についての理解が曖昧だとハマりそうな点にも触れられていました。
(自分はGoを学び始めてしばらくしてからようやく知りました...w)
DBやAPIで扱う際はstringで、などルール化についても言及されており、巨大な小数や計算を扱う際にはこちらでおさらいしたいなと思える発表でした。

「🪦問題」から考えるGoのUnicodeサポート [20min]

gocon.jp

SpannerとGoでサービス開発をしたときに、「🪦問題」に遭遇しました。 🪦が\U0001faa6になってしまった事象に遭遇したところから、Unicodeのリリースサイクルと、Goの追随状況、Unicodeサポート方法、spanner.NullStringを通してfmt.Sprintfの実装方法を調べました。 本セッションでは、調査した知見を共有することで、GoのUnicodeサポートについて少し詳しくなり、spanner.NullStringやfmt.SprintfとUnicodeのハマりどころを知ってもらえるセッションをお届けします。

株式会社ARIGATOBANKのTakahito Yamatoyaさんによるセッションです。
墓石のEmojiを扱えなかったというUnicodeの闇に触れています。

こちらはUnicode13.0で新たに追加されたEmojiとのことです。
自分はUnicodeについて全く明るくなかったのですが、Emojiのリリース、iOS/Androidの対応、Goの対応といった一連のタイムラインについて初めて知りました。
iOS/Androidがサポートしてから大体100日ほどの規模で遅れてGoが対応する、といった流れのようで、そのため新しいEmojiを使う場合にはGoのバージョンによって挙動が変わるとのこと。
(墓石のEmojiはGo1.16だと対応しているが1.15だと\U0001faa6になってしまうとのこと...!)
Unicodeの歴史から解説されており、教訓までまとめられていました。Unicodeコワイ。

まとめ

これらの後にLTも続いていますが、気づけばボリューミーな記事になってしまったため割愛させていただきます。
全体を通して「Goの中級者がさらにステップアップするために」といったレベル感のgopherをターゲットにした内容が多かったのかな?という印象で、個人的には大変満足なカンファレンスでした。
次回のカンファレンスではいよいよジェネリクスの話題が登場するんでしょうか。何が来るのか今から楽しみですね。