GoConference2019Spring参加記
5/18(土)に東京で開催されたGoConferenceというイベントに、メルカリさんのスカラーシップで参加させて頂きました!
このイベントは1年に2回東京で開催されており、メルカリさんをはじめとする有志企業によって運営されているそうです。400人を超える参加者を抱えながら参加費を無料に抑えて開催してくださっているというのはすごいことで、本当にスポンサーさんに感謝するばかりです。
今回はメルカリさんのスカラーシッププログラムに申し込ませて頂き、交通費・宿泊費の補助だけでなく、イベント前日にはGoogle本社からのGoTeamの方々も交えたランチ、オフィスツアーや社内勉強会への参加まで提供頂きました。本当に盛りだくさんの内容で良い経験になりました。
Sessions
早速ですが、特に興味を持ったセッションについていくつかご紹介したいと思います。
Keynote
Keynote(オープニングトーク的なやつ)はGoTeamのKatie HockmanさんによるGoProxyに関する話題でした。go getした時に実はソースコード取ってくるのではなく、GoogleのProxyサーバーを挟んで色々やってくれているというお話です。
Great keynote by @katie_hockman today at #gocon #gocon_hall pic.twitter.com/CVRHVqjMFS
— Julie Qiu (@JQiu25) 2019年5月18日
Julieさんも一緒に来て頂いていたGoTeamの一人です。
Modules
go modで生成したgo.modとgo.sumをレポジトリにおいておくと、go get時に関連モジュールを(依存関係を解消する形で)勝手に取ってきてくれるというもの。例えば別の依存パッケージが同じパッケージの別バージョンを参照している場合でも、それらを全て満たすバージョンのものを取ってきてくれるようです。
Mirrors
参照先のソースコードは消えてたり変更される可能性があるので、Proxyサーバーを挟んで1つのパッケージのあるバージョンのソースコードが同一であることを保証しているという内容。具体的にgo getの挙動は次のようになるみたいです。
Checksum Database
取得したソースコードの正当性(第三者によって改竄されていないこと)を保証するためにチェックサムを照合するが、その照合先のチェックサムを1つのデータベースで管理しているという内容です。
www.certificate-transparency.org
上の通りGoの照合システムではマークルツリーという二分木構造を導入しており、それぞれの親ノードのハッシュ値を子ノードのハッシュ値から計算するようにすることで、全体の整合性を保ちながら大量のチェックサムを管理します。GoProxyでは"Trust on One's Use"という考え方に基づき、データベースにレコードがない場合は最初のリクエスト時のハッシュ値を信用してデータベースに保存します。
エラー設計について/Designing Errors
メルカリの@morikuniさんによるエラー処理の設計に関するトーク。ベストプラクティスだけでなく、そこに行き着くまでのエラー処理そのものの根本的な考え方にも触れられていてすごく参考になりました。
未知のエラーを既知とするための方法がエラーハンドリングである
エラーとは、アプリケーションの実行時に起こる想定外の事態です。そのような未知のエラーを明示的にハンドリングし、自分のアプリケーションの一部として取り込むことがエラーハンドリングだという考え方です。
複数の関係者がエラーにそれぞれ異なる情報を求めている
一口にエラーと言っても処理の階層・エラーを表示する対象によって必要な情報は異なり、それぞれの相手に必要十分な情報を提供できるようにエラーを管理しなければいけないということです。
僕自身もWebAPIをGoで書くにあたりエラー処理が一番の悩みの種で、なかなかこれといった方法論を確立できておらず、それが今回の参加の理由の一つでもありました。特に
「階層的なアーキテクチャを採用している場合レイヤーによってエラーの粒度が異なるが、レイヤーごとに別々のエラーを定義して順次変換していった方がいいのか、同じエラーをレイヤー間で共有してしまっていいのか」
ということについて悩んでいたのですが、今回の「同じエラーでも相手によって提供すべきエラーが異なる」という前提の元では、できるだけ大まかなエラーのみをアプリケーション全体で定義して、詳細やレイヤーごとのメッセージ・情報はレイヤーごとに付加していくのが最善なのかなと思いました。
紹介して頂いたfailure/xerrorsライブラリと合わせて近いうちにリファクタリングしてみたいと思います。
Design considerations for Container based Go application
@hgsgtkさんによる、コンテナアプリケーションをGoで構築するときに考慮すべき事項をまとめたセッションです。こちらも具体的な実装に至るまでの思考過程が整理されており、
という流れが明確でわかりやすく、コンテナアプリケーションに限らず多くの場面で使える考え方であると思いました。
また技術面では
などすぐに実践できるテクニックが盛り込まれていたのがとても参考になりました。
CPU, Memory and Go
@sonatardさんによるトーク。GoのCPU・メモリ周りの話から始まり、Goの軽量さの理由や効率的なメモリ管理について紹介して頂きました。
- appendはスライスのサイズが不足しているときに追加のタイミングでメモリを確保する。ヒープのメモリ確保はとても遅いので、あらかじめサイズがわかっている時は初期化時にまとめて確保する方が望ましい。メモリの空間局所性の観点からも、まとめて確保した方がキャッシュのヒット率が上がるので高速化が期待できる。
- Escape Analysis: 関数内の変数はスタック領域に確保されるが、関数を抜けるときに必要な変数(他のスコープに渡したポインタなど)はヒープ領域に移される。
- 変数はメモリアラインメント (64bit/8byte)の単位に沿って確保され、アラインメントを跨ぐような変数確保が発生する場合はパディングにより次のアラインメントに書き込まれる
などのGoの言語仕様を知りました。特に普段何気なく使っている構造体のポインタ渡しなど、メモリ管理など細かい内部処理がうまく隠蔽されており、ユーザーが細かい部分を気にせずとも処理系が自動的に最適化・高速化してくれる使い勝手の良さにGoの人気の一因を垣間見た気がしました。
感想
今回のGoConferenceでは自分の知らない様々な技術を知ることができました。
- go modによる依存関係・チェックサム管理
- Builder PatternとFunctional Optional Pattern
- failure/xerrorsによるエラーハンドリング
- pprofでのプロファイリング・パフォーマンス解析
- APIの実装を簡単にするimpl/wire/gotests/fillstructといったパッケージ
同時に自分の知識のなさを痛感し、これから一層頑張って勉強していかないといけないという大きな刺激になりました。学んだことを書き残すだけでなく、今後自分のコードのリファクタリングを通して実践していければと思っています。
おまけ:前日・当日の様子
前日はまずメルカリの社員さん(@tenntennさん、@codehexさん)、Googleの@ymotongpooさん、さらにGoogleの本社からのGoTeamからの3人とご一緒させて頂きました。会話は全て英語で、Go2(Generics/Contract)やエラー処理のノウハウについて、色々質問させて頂きました。英語力不足で踏み込んだ話がなかなかできなかったのが残念なところです...ちなみにGoTeamで多く使われているエディタはVSCodeやVimだそうです。
その後はオフィスツアーと社内勉強会に案内して頂きました。社内勉強会は何か1つのトピックについて話すというよりはそれぞれが持ち寄った話題を共有するという雰囲気でした。今回はスカラーシップ生の質問を中心に色々教えて頂きました。ちなみにメルカリのGoTeamで多く使われているエディタはGoLandとVim、ついで VSCodeやPlayground(嘘です)だそうです。
当日はリクルートさんのオフィス(グラン東京サウスタワー)が会場でした。きれい・広い・眺めがいいと素晴らしい会場でした。
きた
— ほしさきひとみ (@HitomiHoshisaki) 2019年5月18日
#gocon #gocon_hall pic.twitter.com/Dnbxm3PSQW
スポンサーさんによるフリースペースもあり、Gopherくん特製カップのコーヒも提供して頂けました。
懇親会、料理豪華。気づいたら懇親会始まってて乾杯どき逃した💧 #gocon pic.twitter.com/CdsOpU7Hh7
— たか (@happylifetaka) 2019年5月18日
参加記は以上になります。最後までお読み頂きありがとうございました!