2020年2月2日日曜日

さようならPython、こんにちはGo

https://yakst.com/ja/posts/5253
シェアしました。

以前はPythonで書いていたようなタスクを、最近ではGoで書くようになったという筆者による、Pythonと比べたGoの良さ、あるいは足りない部分のまとめ

原文
Goodbye Python. Hello Go. (English)
翻訳依頼者
D98ee74ffe0fafbdc83b23907dda3665 Df3136f800e7ed9931ed5f9f1afad935
翻訳者
Df3136f800e7ed9931ed5f9f1afad935 mtsk
翻訳レビュアー
D98ee74ffe0fafbdc83b23907dda3665 doublemarket
原著者への翻訳報告
502日前 原文へのコメントで報告済み 編集

私は、以前はPythonで書いていたようなたくさんの処理でGo言語を使っています。たとえば下記のような処理が挙げられます。
  • Amazon S3に保存されているCloudfrontのログの処理
  • S3内外への巨大な(テラバイト級の)ファイルを移動する処理
  • データベースとS3間において同期済ファイルのマッチングする処理
ほんとんどが一度きりの処理であり、そのためスクリプト言語で書くことが理想的です。そのプログラムは、すばやく書く必要があり、すぐに捨てられる可能性が高いです。いつもこれらのタスクは新しくユニークなものだから、再利用できるコードは最小限となります。
以下に、Pythonの代わりに、Go言語を利用することの優位点を挙げます。

コンパイラを備えているのがよい

私はPythonで、定期的につまらないミスをします。変数名・関数名を間違えたり、誤った引数を渡したりします。開発ツールがこれらを見つけてくれますが、これらのツールは大抵、特殊な初期設定が必要です。未だにpylintを簡単に設定できたためしがないですし、設定を求める本格的なIDEが好きではありません。
最悪なケースは、変数のミスタイプが、条件分岐の裏に隠れてしまうことです。スクリプトは、数時間実行された後、エラーを引き起こします。そして、すべて台無しになった後に、再実行する必要があります。
ユニットテストにより、多くのこの問題を見つけることができます。しかし、100% のカバレジにすることは困難ですし、一回限りのスクリプトのためにユニットテストのための時間を費やしたくないです。
コンパイル言語は、これらの問題をすべて解決してくれます。コンパイラがこれらのミスを見つけてくれます。この理由で、数百行以上のデータを扱うために、Go言語が好きです。

開発スピード

コンパイラ言語が持つデメリットは、開発スピードが遅くなることです。これは、C/C++、Javaにおいては特に当てはまります。
開発スピードが最小限に抑えられていることがわかっている場面では、Goは十分にシンプルです。私はまだPythonをスピーディーにかけますが、go言語の生産性は、pythonで書く場合に対して、85%くらいです。
85%は悪くない数値です。なぜなら、コンパイラを使うことで、細かいミスが大いに減るからです。

並列処理における優位

知っての通り、Goは、はじめから並列処理向けに作られたものです。
私達のチームではよく、S3やデータベースにおける大量のデータを処理するために、並列処理のプログラムを必要としています。
もしタスクがIOに負荷をかけるものなら、Pythonのスレッドを用いれば解決できます。しかし、CPUに負荷をかけるタスクであれば、Pythonはグローバルインタプリタロック(訳注:LL言語のスレッドが持つ排他ロックの仕組み)の観点から難しいです。
私は、マルチスレッドなGo言語において、特別なことをしなくてもシンプルに処理が進む様子を楽しんでもいます。あなたが、マルチスレッド処理中のPythonにCtrl-Cを使ったとき、何の問題もありませんでしたか?

デプロイ容易性

シングルバイナリを扱うことが好きです。私はよく、EC2でコードを実行します。スクリプトと、S3・データベースとの通信経路をより近づけるためです。Pythonでやる場合は、必要なすべてのパッケージがリモートマシン上にインストールされていること、他の同僚がインストールしているなにかとコンフリクトしないこと、を保証する必要があります。
Virtualenvが大抵のこの問題を解決してくれますが、やっぱりGo言語の方が簡単です。
大抵は、Macのgo言語のコードをLinux用にクロスコンパイルし、それをリモートマシンへコピーして、実行するだけです。すべての依存性はバイナリの中に内包されています。

一貫的なスタイル(フォーマッティング)

はじめのうちは、gofmtツールにいらいらしました。とりわけ、スペースの代わりにタブインデントを使うことが辛いです。普通じゃないと思いました。
しかし、使っているうちに、gofmtに依存するようになりました。何の配慮もせずとも自動フォーマットされることで、フォーマット整形から開放されました。すべての私のコードは、私の担当するどのプロジェクトであっても、常に一貫したフォーマットスタイルに保たれます。フォーマット整形は、Go言語の標準ツールの特徴だからです。
Pythonにおいて、同じような効果(一貫したフォーマット)を得るためには、よりコストがかります。私は、pylintを正しく設定し、どのプロジェクトでも一貫していることをチェックをしなければいけません。

ツールにおける優位

この例の一つに、ちょうどgofmtが挙げられます。私が使うどのエディタ(VSCode, vim, Sublime Text)においても、すべての優れたGo言語の拡張機能が利用できます。これが、Go言語が標準機能としてツールを提供していることのメリットです。
このメリットの結果として、IDEを使うことなしに、Javaに似たようなインテリセンス(訳注:補完機能)が得られます。Pythonにおいて、私はこれまで、この機能に近づいたことは一度もありません。

足りない部分

私がGo言語に対する批判を目にするときはいつも、Goの欠けている機能(ジェネリクスのような)に起因しています。私は一度も、ジェネリクスがないことによって、大きな問題に出くわしたことはありません。(あなたが、mapやsliceによってどれだけのことができるかを知ると、驚くでしょう。)しかし、私は他の多くの問題に直面しました。

Go言語は意志を主張しすぎる

Go言語は、今まで書いた言語の中でも、主張する言語です。スペースの代わりにタブを強要される(あなたがgofmtを利用していると仮定して)ことから始まり、特定のディレクトリ構造を利用すること、環境変数GOPATH内でコードを構築することまで。これら多くのGo言語の特徴は、容易に変えられません。
Go言語の学習コストが低い理由の一つは、これらの特徴を変えられないからです。もし、大文字で始まる名前(関数・変数など)を、外部公開したくなければ、そのときは非常に良くないです。幸いなことに、これらは私にとっての厄介者ではないですが、他のもののことであれば、理解できました。
Pythonはもっともっと柔軟です。

ライブラリが提供しているものが少ない

この観点において、PythonとGo言語を比較するのはフェアではありません。Go言語の方が非常に新しいです。しかし私が、Go言語がサポートしていない機能を見つけたとき、困惑します。組み込み関数であるべきコードがStackOverflowに投稿され、さらにはすべての人がそのコードをコピーして自分のプロジェクトに貼り付け問題がないように振る舞ったときには、さらに困惑するでしょう。
2つの例(ここ数年の間で思い浮かぶ例):
  • sliceのソート(幸いなことにGo1.8以降は提供されています)
  • Math.roundが、integerのみを扱え、float変数が扱えない(たとえば、.5に丸めたい場合などで)。さらには、Go1.10以前には、Math.roundさえありませんでした。
そのとおり、これらのうちいくつかはGo言語がジェネリクスを持たないことに起因しますし、Go言語の開発者が、絶対に必要なもののみを標準ライブラリに追加する戦略に従っているからでもあります。
私は、上記の2つの点も理解しています。ですが、自分で実装しなければいけない細かい機能に遭遇したら、やっぱり煩わしいです。
Go言語が発展するにつれ、これらの煩わしさが少なくなっていくことを願います。
次の記事
MySQLデータベースパフォーマンスのためのLinux OSチューニング
前の記事
MySQLのストアドプロシージャ、ファンクション、トリガーのパフォーマンスが悪いのはなぜか

0 コメント:

コメントを投稿