シェアしました。
以前はPythonで書いていたようなタスクを、最近ではGoで書くようになったという筆者による、Pythonと比べたGoの良さ、あるいは足りない部分のまとめ
- [Python]
- [Go (golang)]
私は、以前は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言語が発展するにつれ、これらの煩わしさが少なくなっていくことを願います。
同じタグの付いた翻訳済み記事
Go (golang)
0 件のコメント:
コメントを投稿