YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

OSCON 2013でのGo関連の発表

はじめに

こんにちは、Go界の平賀源内です。さて、先月末にOSCON 2013がオレゴンで開催されましたが、その中発表でいくつかGo関連で話題になったものもあったので、一つまとめてみようと思います。

Go関連の発表

Go関連の発表は以下の7つでした。(発表時間順)

特に最後の @bradfitz による dl.google.com をGoで置き換えた話はかなり話題になっていましたね。というわけで以下、僕が注目した順に簡単に内容を紹介します。

dl.google.com: powered by Go (by Brad Fitzpatrick)

スライドはGo製のオリジナルツールで次のURLでホスティングされています。

数多の著名なオープンソースプロダクトを作ってきた @bradfitz 先輩ですが、いまはGoのコアチームで働いています。そんな彼が、Google社内でプロダクションユースでGoが使われている例としてdl.google.comをC++からGoに移植した例を紹介し、その中で使われているgroupcacheについても紹介しています。

スライド概要

  • (スライド #01-#11)Googleのコンテンツダウンロード用サーバであるdl.google.comは、元々2007年にC++で実装されていたが、リクエストが増加するに連れてサーバが逼迫され、速度が有り得ないほど遅くなったので、 @bradfitz はじめとするGoチームが「俺らが書き換えてやるよ!」と言って2012年に書き換えた。
  • (スライド #12-#17)ここで「なぜコードは悪くなっていくのか」について語っている。はじめは良くても、複雑な要件に対応するためコードも複雑になり、また前提とする環境やスケール感も変わり、さらにドキュメントやテストもないハックやワークアラウンドが増え、メンテナーもどんどん出入りし、あるいは出て行くだけで、メンテがされなくなっていくためである。
  • (スライド #18-#19) Googleでは上に挙げたような前提が日々変化していて、開発当時は素晴らしかったコードもすぐに古びたものになってしまう。実際にdl.google.comの場合は、シングルスレッドのイベントループが実装されていて、マルチコアCPUでも1コアしか消費せずに固まっていた。
  • (スライド #20-#30) 根本原因はシングルスレッドのイベントループとコンテンツをローカルディスクから配布していたことにあり、それを回避するために諸々行ったが、そもそものイベントループ内でNバイトのデータをコピーするだけでありえない量のコードを書かなければいけなかった。(node.js、Twisted等々他のイベントループを持つフレームワークでも同様)
  • (スライド #31-#34) Goではそもそも並列性が言語仕様レベルでサポートされてるので、さらっと書けた。その後、少しずつ既存のC++製の部分を置き換えていって、最終的にGo製に置き換わって、遅かったローカルディスクからのデータ読み込みもblobstoreを使うようになり、スタートアップも早くなった。
  • (スライド #35-#42)dl.google.comではほぼ標準パッケージしか使っていない。net/http、ioのパッケージ内にファイルサーバに必要な型や関数がすべて定義されている。
  • (スライド #43-#47)groupcacheの紹介。memcachedの代替をするクライアントとサーバ両方のためのライブラリ。poolとpeerを宣言して、その後グローバルで一意なgroupを宣言する。groupにキーを指定すると値が取れる。groupはpeerグループ内で共有され、キーに対応する値はpeerグループ内のいずれかのpeerから取得される。 
  • (スライド #48-#54)dl.google.comではchunkとio.SectionReaderをうまく使い、複数の値を読み込んでデータを結合して返している。結果としてHTTPの煩わしいロジックから開放され、純粋にビジネスロジックの実装に集中できた。
  • (スライド #55-#58)サービス自体をバイナリ1つに出来たし、すごくよかった。
  • (スライド #59)いいことづくめ
  • (スライド #60-#63)C++版を再実装する理由が見当たらない。dl.google.comの内容はほとんどオープンソースになってるからみんな使ってね。

というわけで、groupcacheがこの日に公開されました。

Go Best Practices (by Francesc Campoy Flores)

こちらもGoのコアチームにいる @compoy83 からのGoのベストプラクティス集。 @bradfitz のプレゼンはGoの啓蒙寄りな内容だったのに対し、こちらはすでにGoを書いているエンジニアを対象としたノウハウ集でした。挙げられていたベストプラクティスは次のとおり。

こちらもスライドはgo.talksに置いてある。

ベストプラクティスの内容は次の通り。

  1. エラーハンドリングをまず行い、ifのネストを避けろ
  2. エラーハンドリングの繰り返しを避けるために、一時的な型を作る。必要であればtype switchで例外的処理を扱ったり、switchで変数宣言する。関数アダプタを使って例外処理とロジックを分ける。
  3. 大事な情報から先に書く。ライセンス情報やドキュメント。import内ではグループ(標準パッケージ or 3rd party)ごとに空行で区切りをつける。補助関数や補助的な型は後ろの方に書く。
  4. ドキュメントを書く
  5. 命名時は読んで意味が分かる一番短い名前を付けるように努める
  6. パッケージは複数ファイルで構成する。net/httpを例として次の3つの規則を紹介。「長いファイルは分割する」「テストと本体は分ける」「ドキュメントもdoc.goというファイルに分ける」
  7. パッケージを"go get"した時に便利なようにする
  8. 本当に必要なものを書く。structでなくinterfaceを引数に取ることでテストしやすくなる。
  9. 独立したパッケージをきちんと分けておく。
  10. API内で並列なコードを避ける。同期なAPIを提供すれば、呼び出し側で簡単に並列にできる。
  11. 状態管理にgoroutineを使う。
  12. goroutineリークを避ける。buffered channelやquit channelを使う。

Go Language for Ops and Site Reliability Engineering (by Gustavo Franco)

GoogleのSites Reliability Engineer(インフラ部隊)の人が語るGo言語。このプレゼンはOSCONの3ヶ月前にO'Reilly主催のHangout on Airで既に話されていましたので、動画も貼りました。いわゆるアプリケーションエンジニアとは異なる観点からのGo言語の評価、という点で興味深いプレゼンです。


O'Reilly Webcast: Go Language for Ops and Site ...

スライドの要点は下記

  • インフラエンジニアからしたら、ただ書き捨てのスクリプトが欲しいだけで、新しい言語は覚えたくない。ワンライナーは便利なので使い続けるけど、できれば道具として見れる言語を少しだけ覚えるだけに留めたい。
  • その点でGoは、オープンソースだし、バイナリが出来ればそれを動かすだけで済むし、ビルドファイルは要らないし、ビルドも速いし、GCはあるし、読みやすいし、RE2は使えるし、テスト、ベンチマーク、プロファイラが全部標準で入ってるので楽。標準パッケージが豊富なのも良い。
  • またgoroutineとchannelを用いた並列性のサポートがはじめからあるのもよい。
  • 最近のLLが持っているような特徴も兼ね備えていて良い。(map、slice、モジュール機構、struct、メソッド、ポインタ演算のないポインタ)
  • Google社内はもちろん、Google外にも多くのプロダクションレベルのインフラ環境での利用がある。

啓蒙という視点ではなく、現実的な視点からプロダクションに耐える言語だということを説明しているプレゼンでした。

Rethinking Errors: Learning from Scala and Go (by Bruce Eckel)

今回のOSCONでは珍しいGoogler以外からのGoのプレゼン。その意味で、非常に貴重だし、なによりGoを始めるとすぐに取り沙汰されるGoにおけるエラー処理を言及したプレゼン。資料はこちら。タイトルにはGoとScalaしか書いてないけど、むしろサンプルはPythonで説明している。

スライドの要点

  • 新しいエラー処理機構の潮流として正常系の返り値とエラーを同時に返すというやり方がある
  • C, C++, Java, Python, Ruby, PHPと、数値またはシグナルを返すところから始まったエラー通知が徐々に例外処理へと変化していったが、制限も大きかった。
  • Goは初期はエラー処理機構はなく後からpanicとrecoverが追加され、ScalaではEitherまたは専用型で、Pythonでは例外以外にもGoのようにタプルでエラーを返したり専用オブジェクトを返す方法をとれる
  • Pythonでの例ではあるが、スピーカーの結論は必要以外には例外処理を使わず、通常の分岐処理で対応できるようにしよう、という事のようです。

Goの話はタプルで正常値とエラーを同時に返して、通常の分岐処理で対応できている点がいいね、という話しか出てきてなかったです。

How Learning Go Made Me A Better Programmer (by Johan Euphrosine)

こちらはGoogle App EngineのDeveloper Program Engineerの @proppy による、Goの優れたところ紹介集。時々PythonJava、node.jsとの比較をしながらGoの良いところを挙げている。

このスライドで上がっているのは次の点

  • 可読性(Pythonとの比較。ほぼPseudo Codeだよ。言語仕様だけでなく、go fmtなどのツールが標準であるのも良い)
  • エラーハンドリング(PythonJava、node.js、Haskell、Rustとの比較。
  • 標準パッケージ(非常にリッチ。Pythonと比較してもリッチ。)
  • XMLとJSONの扱い(標準パッケージでサポートされている。XMLとJSONの扱いで一貫性がある。Pythonとの比較。)
  • パッケージングと配布(ツールが良きに計らってくれて非常に楽。ビルドファイル要らない。PythonJava、node.jsとの比較)
  • ツール(標準でテスト、文法チェック、パッケージング等々行なってくれる。Python、node.jsとの比較)
  • 並列性のサポート(ランタイムに含まれている。node.js、Pythonとの比較。)
  • Interface(暗黙的に判定、Compositionも可能。Pythonのduck typingとの比較。)
  • Composition(複数のstructを組み合わせられる。Interfaceと直交する機能。PythonRubyのmixinとの比較。)
  • Community(もりあがってるよ)

Introduction to Go (by Francesc Campoy Flores)

"A Tour of Go" を使ったチュートリアルセッションでした。みなさんもGoを始める時はまずは"A Tour of Go"で文法を学ぶのがベスト。(演習問題は飛ばしていいと思う。)

Office Hour with the Gophers (by Brad Fitzpatrick, Johan Euphrosine, Francesc Campoy Flores)

オフィスアワーです。僕も @bradfitz と @compoy83 にまだ直接会って話したこと無いので話してみたい。 @proppy はもしかすると今度のPyCon APAC 2013に来るよ。

おわりに

Goはまだまだ若い言語ですが、OSCONのような場所でしっかりと実例を紹介できるところまで来ていると認識出来たのは素晴らしいですね。groupcacheは今回の目玉でしたが、Google SREのGastavoのスライドにあったように、DockerやPackerやJujuといったインフラ系のツールにGoが使われている点で、流行り廃りでない、本物の存在感を感じ取ることが出来るような気がします。

これからのGoが楽しみですね!